OpenCV中文网站

 找回密码
 立即注册
搜索
热搜: 安装 配置
查看: 30604|回复: 27

字符分割提取

[复制链接]
发表于 2013-11-22 05:59:46 | 显示全部楼层 |阅读模式
本帖最后由 anqing 于 2013-11-22 06:50 编辑

看到有个帖子是关于字符分割,识别的,想回复图片,但不知道怎么回复,这里只好另起一帖。
源图片:
032836nr9glwch0fl7u33g (1).jpg
像这些图片的字符就比较好操作,每个字符都独立,不连在一起,所以轮廓检测最好了。
所以就有:
1.源图片转成单通道的灰阶图片
2.对灰度图像进行阈值操作得到二值图像


grey.jpg

3.轮廓检测(只获取最外层的)
4.遍历所有检测到的轮廓,用cvBoundingRect()得到每一个轮廓的外接矩形
grey2.jpg

5.这步就容易多了,抠它们出来就行
grey3.jpg





搞定
回复

使用道具 举报

 楼主| 发表于 2013-11-22 06:03:57 | 显示全部楼层
识别可以用KNN分类器来训练识别(NN, SVM也行)。
回复 支持 反对

使用道具 举报

发表于 2013-11-24 00:04:02 | 显示全部楼层
在投影法处理这张图片的时候,我可以得到6和7 ,但是8就不怎么好处理,也不知为什么。还有,您的提取外轮廓的代码方便给我参考吗?
678.bmp
6.jpg
7.jpg
8.jpg
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-11-24 01:00:45 | 显示全部楼层
本帖最后由 anqing 于 2013-11-24 03:23 编辑
peterluy 发表于 2013-11-24 00:04
在投影法处理这张图片的时候,我可以得到6和7 ,但是8就不怎么好处理,也不知为什么。还有,您的提取外轮廓 ...
  1. #include "stdafx.h"  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4. #include "cxcore.h"  
  5. using namespace cv;  
  6.   
  7.   
  8. int main(int argc, char* argv[])  
  9. {  
  10.     IplImage* imgSrc = cvLoadImage("D:\\4.jpg",CV_LOAD_IMAGE_COLOR);  
  11.     IplImage* img_gray = cvCreateImage(cvGetSize(imgSrc), IPL_DEPTH_8U, 1);  
  12.     cvCvtColor(imgSrc, img_gray, CV_BGR2GRAY);  
  13.     cvThreshold(img_gray, img_gray,100, 255,CV_THRESH_BINARY_INV);// CV_THRESH_BINARY_INV使得背景为黑色,字符为白色,这样找到的最外层才是字符的最外层  
  14.     cvShowImage("ThresholdImg",img_gray);  
  15.     CvSeq* contours = NULL;  
  16.     CvMemStorage* storage = cvCreateMemStorage(0);   
  17.     int count = cvFindContours(img_gray, storage, &contours,  
  18.         sizeof(CvContour),CV_RETR_EXTERNAL);  
  19.     cvReleaseMemStorage(& storage);   
  20.     printf("轮廓个数:%d",count);  
  21.     int idx = 0;  
  22.     char szName[56] = {0};  
  23.     int tempCount=0;  
  24.     for (CvSeq* c = contours; c != NULL; c = c->h_next) {  
  25.          CvRect rc =cvBoundingRect(c,0);  
  26.          cvDrawRect(imgSrc, cvPoint(rc.x, rc.y), cvPoint(rc.x + rc.width, rc.y + rc.height), CV_RGB(255, 0, 0));  
  27.   
  28.       // if () {这里可以根据轮廓的大小进行筛选,上面源图片有瑕疵可以用腐蚀,膨胀来祛除  
  29.       //    continue;  
  30.      //  }  
  31.          
  32.         IplImage* imgNo = cvCreateImage(cvSize(rc.width, rc.height), IPL_DEPTH_8U, 3);  
  33.         cvSetImageROI(imgSrc, rc);  
  34.         cvCopyImage(imgSrc, imgNo);  
  35.         cvResetImageROI(imgSrc);  
  36.         sprintf(szName, "wnd_%d", idx++);   
  37.         cvReleaseImage(&imgNo);  
  38.     cvNamedWindow(szName);  
  39.         cvShowImage(szName, imgNo);  
  40.   
  41.     }  
  42.       
  43.     cvNamedWindow("src");  
  44.     cvShowImage("src", imgSrc);  
  45.     cvWaitKey(0);  
  46.     cvReleaseMemStorage(&storage);  
  47.     cvReleaseImage(&imgSrc);  
  48.     cvReleaseImage(&img_gray);  
  49.     cvDestroyAllWindows();  
  50.     return 0;  
  51. }  
复制代码
但是你的这张图片会有小轮廓,可以根据矩形的宽或高判断去掉。不能直接用。投影法我一点都不会,你能不能也共享下啊
678.jpg
回复 支持 反对

使用道具 举报

发表于 2013-11-24 01:46:58 | 显示全部楼层
anqing 发表于 2013-11-24 01:00
但是你的这张图片还需要令外的预处理如加大点亮度,去掉一些小轮廓。不能直接用。投影法我一点都不会,你能 ...
  1. // test1122.cpp : 定义控制台应用程序的入口点。
  2. //

  3. #include "stdafx.h"
  4. #include "cv.h"
  5. #include "cxcore.h"
  6. #include "highgui.h"
  7. #include "iostream"
  8. #include <vector>
  9. #pragma comment(lib,"highgui210d.lib")
  10. #pragma comment(lib,"cxcore210d.lib")
  11. #pragma comment(lib,"cv210d.lib")
  12. using namespace std;

  13. CvRect CutTopButtom(IplImage *src);
  14. vector<CvRect>leftright;
  15. //vector<CvRect>::iterator iter;
  16. int lstart=0,lend=0,lrun=0;
  17. int lastStart=0,lastEnd=0;
  18. IplImage *dst[10];
  19. CvRect rectRoi;


  20. void FindLeftRight(IplImage *src);
  21. void RememberLeftRight(IplImage *src,int lstart,int lend);
  22. void ShowAndCut(IplImage  *src[]);



  23. IplImage * raw=cvLoadImage("678.bmp",0);
  24. IplImage * img;

  25. int _tmain(int argc, _TCHAR* argv[])
  26. {   
  27.         cvSmooth(raw,raw);
  28.         cvThreshold(raw,raw,70,255,CV_THRESH_BINARY);
  29.         IplConvKernel *element=0;                                //结构元素
  30.         cvMorphologyEx(raw,raw,NULL,element,CV_MOP_OPEN);        //开运算
  31.         rectRoi=CutTopButtom(raw);
  32.     img=cvCreateImage(cvGetSize(raw),IPL_DEPTH_8U,1);
  33.         cvCopy(raw,img);
  34.         FindLeftRight(raw);
  35.        
  36.        

  37.         return 0;
  38. }


  39. CvRect CutTopButtom(IplImage *src)
  40. {

  41.        
  42.         int* h=new int[src->height];
  43.         memset(h,0,src->height*4);
  44.         int hstart,hend,x,y,zhongdian;  
  45.         CvScalar s;
  46.         for(y=0;y<src->height;y++)  
  47.         {  
  48.                 for(x=0;x<src->width;x++)  
  49.                 {  
  50.                         s=cvGet2D(src,y,x);           
  51.                         if(s.val[0]==0)  
  52.                                 h[y]++;      
  53.                 }     
  54.         }
  55.         for (int j=0;j!=src->height;j++)
  56.         {
  57.                 if (h[j]>15)
  58.                 {
  59.                         zhongdian=j;
  60.                         hstart=zhongdian;
  61.                         break;
  62.                 }
  63.                 else
  64.                         continue;

  65.         }
  66.         while(zhongdian!=src->height)
  67.         {
  68.                 if (h[zhongdian]<10)
  69.                 {
  70.                         hend=zhongdian;
  71.                         break;
  72.                 }
  73.                 else
  74.                         hend=zhongdian;
  75.                 zhongdian++;
  76.         }
  77.         CvRect rect=cvRect(0,hstart-10,src->width,hend-hstart+20);
  78.         cvSetImageROI(src,rect);
  79.        
  80.        
  81.         return rect;
  82. }


  83. void FindLeftRight(IplImage *src)
  84. {

  85.         int* v=new int[rectRoi.width];
  86.         memset(v,0,rectRoi.width*4);
  87.         int x,y;  
  88.         CvScalar s;  
  89.         for(x=0;x<rectRoi.width;x++)  
  90.         {  
  91.                 for(y=0;y<rectRoi.height;y++)
  92.                 {  
  93.                         s=cvGet2D(src,y,x);           
  94.                         if(s.val[0]==0)  
  95.                                 v[x]++;  
  96.                         else
  97.                                 continue;
  98.                 }         
  99.         }
  100.        
  101.         if (lend<=rectRoi.width)  
  102.         {
  103.                 for (int i=0;i<rectRoi.width;i++)
  104.                 {
  105.                         if(v[i]>10)
  106.                         {
  107.                                 lrun=i;
  108.                                 lstart=lrun;
  109.                                 break;


  110.                         }
  111.                         else
  112.                                 continue;
  113.                 }
  114.                 if (lstart==lrun)
  115.                 {
  116.                         for (lrun;lrun<rectRoi.width;lrun++)
  117.                         {
  118.                                 if (v[lrun]<5)
  119.                                 {
  120.                                         lend=lrun;
  121.                                         break;
  122.                                 }
  123.                                 else
  124.                                         continue;
  125.                                

  126.                         }
  127.                 }
  128.                 RememberLeftRight(src,lstart,lend);
  129.         }
  130.        
  131.         else
  132.                 ShowAndCut(dst);

  133.        
  134.        
  135.        
  136. }


  137. void RememberLeftRight(IplImage *src,int lstart,int lend)
  138. {
  139.        
  140.         if (lastStart==0&&lastEnd==0)
  141.         {
  142.                 lastStart=lastStart+lstart;
  143.                 lastEnd=lastEnd+lend;
  144.         }
  145.        
  146.         else
  147.         {
  148.                 lastStart=lastEnd+lstart;
  149.                 lastEnd=lastEnd+lend;
  150.         }

  151.         CvRect Rect=cvRect(lastStart-10,0,lastEnd-lastStart+20,rectRoi.height);
  152.         //CvRect Rect=cvRect(lastStart-5,0,lend-lstart+15,rectRoi.height);
  153.         leftright.push_back(Rect);
  154.     rectRoi=cvRect(lend,0,(rectRoi.width-lend),rectRoi.height);
  155.         cvSetImageROI(src,rectRoi);
  156.         FindLeftRight(src);
  157.    

  158. }

  159. void ShowAndCut(IplImage *src[])
  160. {
  161.        
  162.         for (vector<CvRect>::iterator iter=leftright.begin();iter!=leftright.end();iter++,i++)
  163.         {
  164.                 src[i]=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);
  165.                 cvCopy(img,src[i]);
  166.                 cvSetImageROI(src[i],*iter);
  167.                 cvNamedWindow("src");
  168.                 cvShowImage("src",src[i]);
  169.                 cvWaitKey(3000);
  170.                

  171.         }
  172. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2013-11-24 02:06:11 | 显示全部楼层
anqing 发表于 2013-11-24 01:00
但是你的这张图片还需要令外的预处理如加大点亮度,去掉一些小轮廓。不能直接用。投影法我一点都不会,你能 ...

这份代码在我的电脑上运行成功不了诶,在CvRect rc =cvBoundingRect(c,0);  的时候就运行不下去了。不知道为什么!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-11-24 02:38:07 | 显示全部楼层
本帖最后由 anqing 于 2013-11-24 02:50 编辑

把19行的cvReleaseMemStorage(&storage);  注释掉就应该行
还有37行的cvReleaseImage(&imgNo)放在40行即cvShowImage()下面才对,
昨天整理放在txt中搞错了,真是不好意思
回复 支持 反对

使用道具 举报

发表于 2013-12-18 18:07:35 | 显示全部楼层
没来晚,支持一个
回复 支持 反对

使用道具 举报

发表于 2014-1-8 18:45:27 | 显示全部楼层
楼主 方便吧你的代码传一下吗,急需!!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-1-8 21:29:17 | 显示全部楼层
Balvboy 发表于 2014-1-8 18:45
楼主 方便吧你的代码传一下吗,急需!!

http://blog.csdn.net/anqing715/article/details/16883863
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|OpenCV中文网站

GMT+8, 2024-5-4 03:55 , Processed in 0.011874 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表