如何使用OpenCV从名片中删除非文本区域? [英] How to use OpenCV to remove non text areas from a business card?

查看:851
本文介绍了如何使用OpenCV从名片中删除非文本区域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是从扫描的名片图像中删除任何非文本区域,但我不知道执行使用OpenCV的步骤,我已经按照这些步骤,但不知道这是正确的或不是



1)将图像转换为灰度

>

2)二进制图像



3)反转颜色(cv :: bitwise_not)文本



4)蚀刻图像(cv :: erode)



p>

6)使用hough transform(尚未)检测文本行



代码:

  cv :: Mat greyMat = [self.imageView.image CVGrayscaleMat]; 
cv :: Mat bwMat;
cv :: threshold(greyMat,bwMat,128,255,CV_THRESH_BINARY);
cv :: bitwise_not(bwMat,bwMat);
cv :: Mat element = cv :: getStructuringElement(cv :: MORPH_RECT,cv :: Size(2,1));
cv :: erode(bwMat,bwMat,element);
std :: vector< cv :: Point> points;
cv :: Mat_< uchar> :: iterator it = bwMat.begin< uchar>();
cv :: Mat_< uchar> :: iterator end = bwMat.end< uchar>();
for(; it!= end; ++ it)
if(* it)
points.push_back(it.pos());
cv :: RotatedRect box = cv :: minAreaRect(cv :: Mat(points));
plImage * smothedImage = new IplImage(bwMat);
cvSsmooth(smothedImage,smothedImage);
cvCanny(smothedImage,smothedImage,10,100);


解决方案

定义标志的一种方法可能是



如果这是真的,你可以像这样删除标志:



(我使用imagemagick生成以下示例,您应该可以使用opencv)



0) / p>

  imagemagick:convert img0052ir.jpg -threshold 60%monochrome.png 



1)扩大图片,直到所有字母都消失,但标志的某些部分仍然保留。

  orgImg =名片图像
cvDilate(orgImg,curImg,null,Some_Value)//找到一个值,擦除所有字母,但留下标志

  imagemagick:convert monochrome.png -morphology dilate:3 diamond dilated.png 



2)条件性地侵蚀扩张的图像,使用原始图像作为掩码,直到标志再次完成。



这意味着您会腐蚀扩大的图片,但绝不能将像素值设置为低于原始图片中的值。您可以使用原始图片作为掩码来保护图片的某些部分免受更改。



这将恢复所有仍然有一些种子部分的形状,因此只有徽标

  //不知道opencv是否可以在形态操作中使用掩码,
//但是你可以使用erode + max在循环中以获得相同的效果,尽管缓慢
repeat
lastImg = curImg
cvErode(lastImg,curImg,null,1)
cvMax(curImg,orgImg,curImg)
until lastImg == curImg

  imagemagick:convert dilated.png -morphology erode:20 diamond -clip-mask monochrome.png eroded.png 



您现在拥有的图片只有标志且没有文字,请使用此图片删除标志

  imagemagick:convert eroded.png -negate img0052ir.jpg -compose plus -composite test.png 

p>

正如你所看到的,它远非完美。
也许玩弄的阈值,膨胀内核等,在opencv看看这是否可以改善。但我怀疑有一个通用的解决方案,删除所有的标志和没有文字



编辑:添加了一些图片 $ b

my target is to remove any non text area from a scanned business card image but i don't know the steps to perform that using OpenCV , i have followed this steps but don't know this is the right one or not also i don't notice any change in the image (non text areas remains) any idea will be very helpful,thanks.

1) convert the image to grayscale

2) binaries the image

3) invert the colors (cv::bitwise_not) in order to have a white pixels text

4) Erode the image(cv::erode)

5) detect edges using canny

6) detect text lines using hough transform (not yet)

code:

cv::Mat greyMat = [self.imageView.image CVGrayscaleMat];
cv::Mat bwMat;
cv::threshold(greyMat, bwMat, 128, 255, CV_THRESH_BINARY);
cv::bitwise_not(bwMat, bwMat);
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(2, 1));
cv::erode(bwMat, bwMat, element);
std::vector<cv::Point>points;
cv::Mat_<uchar>::iterator it=bwMat.begin<uchar>();
cv::Mat_<uchar>::iterator end=bwMat.end<uchar>();
for (; it!=end; ++it) 
if (*it) 
points.push_back(it.pos());
cv::RotatedRect box=cv::minAreaRect(cv::Mat(points));
plImage* smothedImage=new IplImage(bwMat); 
cvSmooth(smothedImage, smothedImage);
cvCanny(smothedImage, smothedImage, 10, 100);

解决方案

one way to define the logo could be that the logo parts contain fatter lines and larger blobs than the text parts.

If this holds true, you can remove the logo like this:

(I used imagemagick to generate the following samples, you should be able to to the same with opencv)

0) threshold the image (optional)

   imagemagick: convert img0052ir.jpg -threshold 60% monochrome.png

1) dilate the image until all letters are gone, but some parts of the logo still remain.

 orgImg = business card image 
 cvDilate (orgImg, curImg, null, Some_Value) // find a value that erases all letters but leaves the logo

or

 imagemagick:  convert monochrome.png -morphology dilate:3 diamond dilated.png

2) conditional-erode the dilated image, using the original image as the mask, until the logo is complete again.

This means you erode the dilated image, but never set a pixel value to below its value in the original source image. You use the original image as a mask to protect parts of the image from changes.

this will restore all shapes that still have some seed part left, so only the logo

 // Not sure if opencv can use a mask in morphologial operations, 
 // but you can just use erode + max in a loop to achive the same effect albeit slower
 repeat
    lastImg = curImg
    cvErode (lastImg, curImg, null ,1)
    cvMax (curImg, orgImg, curImg)
 until lastImg == curImg

or

 imagemagick: convert dilated.png -morphology erode:20 diamond -clip-mask monochrome.png eroded.png

you now have an image with ONLY the logo and no text, use this image to remove the logo

 imagemagick: convert eroded.png -negate img0052ir.jpg -compose plus -composite test.png

As you can see, it is far from perfect. Perhaps toy around with the thresholding, dilation kernel etc, in opencv to see if this can be improved. But I doubt there is a general solution that removes all logos and none of the text

EDIT: some pictures added

这篇关于如何使用OpenCV从名片中删除非文本区域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆