模式識別中精確定位之垂直和水平投影
阿新 • • 發佈:2019-01-09
在模式識別中常用垂直投影和水平投影對目標物進行精確投影,以便於後期的分割。
示例:
(1) (2) (3)
對上圖一中“靜”精確定位,字型行書剛好將它為連通。(若如不是連筆,後期分割可能將“青”和“爭”分開)
從圖(2)可知:從第三白色部分即可定位出“靜”字的寬度,
從圖(3):即可定位出“靜”字的高度。
垂直投影和水平投影程式碼:
效果圖:上圖(1)(2)(3)<pre name="code" class="cpp">// Vertical_gray_projection.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int _tmain(int argc, _TCHAR* argv[]) { IplImage * src=cvLoadImage("1.bmp"); IplImage *dst = cvCreateImage(cvGetSize(src), 8, 1); IplImage *img = cvCreateImage(cvGetSize(src), 8, 1); cvSmooth(src,src,CV_BLUR,3,3,0,0); cvCvtColor(src,img,CV_BGR2GRAY); cvThreshold(img,dst,50,255,CV_THRESH_BINARY); IplImage* paintx=cvCreateImage( cvGetSize(dst),IPL_DEPTH_8U, 1 ); IplImage* painty=cvCreateImage( cvGetSize(dst),IPL_DEPTH_8U, 1 ); cvZero(paintx); cvZero(painty); int* v=new int[dst->width]; int* h=new int[dst->height]; memset(v,0,dst->width*4); memset(h,0,dst->height*4); int x,y; CvScalar s,t;//可以用來存放4個double數值的陣列,一般用來存放畫素值(不一定是灰度值哦)的,最多可以存放4個通道的 /*typedef struct CvScalar { double val[4]; }CvScalar; */ //垂直投影 for(x=0;x<dst->width;x++) { for(y=0;y<dst->height;y++) { s=cvGet2D(dst,y,x); //cvGet2D() 的函式原型是 : CvScalar cvGet2D (const CvArr * arr, int idx0, int idx1); //函式返回的是一個CvScalar 容器,其引數中也有兩個方向的座標, //但跟我們平常習慣的座標不一樣的是,idx0代表是的行,即高度,對應於我們平常座標系的y, //idx1代表的是列,即寬度,對應於我們平常座標系的x,cvSet2D() 也類似。 //printf("area == %lf\n",s); if(s.val[0]==0) v[x]++; } } for(x=0;x<dst->width;x++) { for(y=0;y<v[x];y++) { t.val[0]=255; cvSet2D(paintx,y,x,t); } } //水平投影 for(y=0;y<dst->height;y++) { for(x=0;x<dst->width;x++) { s=cvGet2D(dst,y,x); if(s.val[0]==0) h[y]++; } } for(y=0;y<dst->height;y++) { for(x=0;x<h[y];x++) { t.val[0]=255; cvSet2D(painty,y,x,t); } } cvNamedWindow("二值影象",1); cvNamedWindow("垂直投影",1); cvNamedWindow("水平投影",1); cvShowImage("二值影象",dst); cvShowImage("垂直投影",paintx); cvShowImage("水平投影",painty); cvWaitKey(0); cvDestroyAllWindows(); cvReleaseImage(&dst); cvReleaseImage(&paintx); cvReleaseImage(&painty); return 0; }