1. 程式人生 > >模式識別中精確定位之垂直和水平投影

模式識別中精確定位之垂直和水平投影

在模式識別中常用垂直投影和水平投影對目標物進行精確投影,以便於後期的分割。

示例:

                (1)                                                                                    (2)                                                                                           (3)

對上圖一中“靜”精確定位,字型行書剛好將它為連通。(若如不是連筆,後期分割可能將“青”和“爭”分開)

從圖(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;
}
效果圖:上圖(1)(2)(3)