模式识别中精确定位之垂直和水平投影

来源:互联网 发布:办公鼠标推荐 知乎 编辑:程序博客网 时间:2024/06/04 19:57

Refer from http://blog.csdn.net/what_lei/article/details/49099223

在模式识别中常用垂直投影和水平投影对目标物进行精确投影,以便于后期的分割。

示例:

                          (1)                                                                                    (2)                                                                                           (3)


对上图一中“静”精确定位,字体行书刚好将它为连通。(若如不是连笔,后期分割可能将“青”和“争”分开)

从图(2)可知:从第三白色部分即可定位出“静”字的宽度,

从图(3):即可定位出“静”字的高度。

垂直投影和水平投影代码:

[cpp] view plain copy
  1. <pre name="code" class="cpp">// Vertical_gray_projection.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <opencv2/opencv.hpp>  
  6.   
  7. using namespace std;  
  8. using namespace cv;  
  9.   
  10. int _tmain(int argc, _TCHAR* argv[])  
  11. {  
  12.         IplImage * src=cvLoadImage("1.bmp");  
  13.     IplImage *dst = cvCreateImage(cvGetSize(src), 8, 1);  
  14.     IplImage *img = cvCreateImage(cvGetSize(src), 8, 1);  
  15.     cvSmooth(src,src,CV_BLUR,3,3,0,0);  
  16.     cvCvtColor(src,img,CV_BGR2GRAY);  
  17.     cvThreshold(img,dst,50,255,CV_THRESH_BINARY);  
  18.     IplImage* paintx=cvCreateImage( cvGetSize(dst),IPL_DEPTH_8U, 1 );  
  19.     IplImage* painty=cvCreateImage( cvGetSize(dst),IPL_DEPTH_8U, 1 );  
  20.     cvZero(paintx);  
  21.     cvZero(painty);  
  22.     int* v=new int[dst->width];  
  23.     int* h=new int[dst->height];  
  24.     memset(v,0,dst->width*4);  
  25.     memset(h,0,dst->height*4);  
  26.       
  27.     int x,y;  
  28.     CvScalar s,t;//可以用来存放4个double数值的数组,一般用来存放像素值(不一定是灰度值哦)的,最多可以存放4个通道的  
  29.                            /*typedef struct CvScalar 
  30.                                   { 
  31.                                  double val[4]; 
  32.                                 }CvScalar; 
  33.                             */  
  34.     //垂直投影  
  35.     for(x=0;x<dst->width;x++)  
  36.     {  
  37.         for(y=0;y<dst->height;y++)  
  38.         {  
  39.             s=cvGet2D(dst,y,x); //cvGet2D() 的函数原型是 : CvScalar cvGet2D (const CvArr * arr, int idx0, int idx1);   
  40.                                  //函数返回的是一个CvScalar 容器,其参数中也有两个方向的坐标,  
  41.                                  //但跟我们平常习惯的坐标不一样的是,idx0代表是的行,即高度,对应于我们平常坐标系的y,  
  42.                                  //idx1代表的是列,即宽度,对应于我们平常坐标系的x,cvSet2D() 也类似。          
  43.             //printf("area == %lf\n",s);  
  44.             if(s.val[0]==0)  
  45.                 v[x]++;   
  46.         }         
  47.     }  
  48.       
  49.     for(x=0;x<dst->width;x++)  
  50.     {  
  51.         for(y=0;y<v[x];y++)  
  52.         {         
  53.             t.val[0]=255;  
  54.             cvSet2D(paintx,y,x,t);  
  55.         }         
  56.     }  
  57.     //水平投影  
  58.     for(y=0;y<dst->height;y++)  
  59.     {  
  60.         for(x=0;x<dst->width;x++)  
  61.         {  
  62.             s=cvGet2D(dst,y,x);   
  63.               
  64.             if(s.val[0]==0)  
  65.                 h[y]++;   
  66.         }  
  67.     }  
  68.     for(y=0;y<dst->height;y++)  
  69.     {  
  70.         for(x=0;x<h[y];x++)  
  71.         {             
  72.             t.val[0]=255;  
  73.             cvSet2D(painty,y,x,t);    
  74.               
  75.         }         
  76.     }  
  77.   
  78.     cvNamedWindow("二值图像",1);  
  79.     cvNamedWindow("垂直投影",1);  
  80.     cvNamedWindow("水平投影",1);  
  81.     cvShowImage("二值图像",dst);  
  82.     cvShowImage("垂直投影",paintx);  
  83.     cvShowImage("水平投影",painty);  
  84.     cvWaitKey(0);  
  85.     cvDestroyAllWindows();  
  86.     cvReleaseImage(&dst);  
  87.     cvReleaseImage(&paintx);  
  88.     cvReleaseImage(&painty);  
  89.     return 0;  
  90. }  
效果图:上图(1)(2)(3)
0 0