OpenCV学习笔记9 (Hough线变换)


1.hough变换调试程序


#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"



int _tmain(int argc, _TCHAR* argv[])
{
	IplImage* src = cvLoadImage("D:\\PERSONAL\\VC++\\2016\\毕业论文\\论文图表文件he文字资料\\模式识别\\picture\\模式1和2处理\\canny\\J11.jpg",CV_LOAD_IMAGE_GRAYSCALE);
	IplImage* src3 = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);//三通道显示
	CvMemStorage *storage = cvCreateMemStorage();  
    CvSeq *lines = 0;  

	cvMerge(src,src,src,NULL,src3);
	cvNamedWindow("1");
	cvShowImage("1",src);
	lines = cvHoughLines2(src,storage,CV_HOUGH_STANDARD,1,CV_PI/180,100,0,0); 


	int i = 0; 
H: 
	if(i<lines->total)
	{
		float* line = (float*)cvGetSeqElem(lines,i);
		float rho = line[0];
		float theta = line[1];
		CvPoint pt1, pt2;
		double a = cos(theta), b = sin(theta);
		double x0 = a*rho, y0 = b*rho;
		pt1.x = cvRound(x0 + 1000*(-b));
		pt1.y = cvRound(y0 + 1000*(a));
		pt2.x = cvRound(x0 - 1000*(-b));
		pt2.y = cvRound(y0 - 1000*(a));
		cvLine( src3, pt1, pt2, CV_RGB(255,0,0), 1, CV_AA, 0 );
		cvCircle(src3,pt1,5,CV_RGB(0,255,0),2,8,0);
		cvCircle(src3,pt2,5,CV_RGB(0,255,0),2,8,0);
		cvShowImage("3",src3);
		printf("i = %d\n",i);
		printf("a = %f,b = %f\n",a,b);
		printf("roh = %f,theta = %f\n",rho,theta);
		printf("x0 = %f,y0 = %f\n",x0,y0);
		printf("x1 = %d,y1 = %d\n",pt1.x,pt1.y);
		printf("x2 = %d,y2 = %d\n",pt2.x,pt2.y);
		i++;
	}
        

	char c(0);
	while (1)
	{
		cvShowImage("3",src3);
		c = cvWaitKey(1);
		if(c == 13)
			goto H;
		if(c == 27)
			break;
	}

	cvDestroyWindow("1");
	cvReleaseImage(&src);
	
	return 0;
}

// if(theta>2.9 || theta<0.2) //vertical


2.hough提取水平线程序

// deal.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"



int _tmain(int argc, _TCHAR* argv[])
{
	IplImage* src = cvLoadImage("D:\\...\\H11.jpg",CV_LOAD_IMAGE_GRAYSCALE);
	IplImage* src3 = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);//三通道显示
	CvMemStorage *storage = cvCreateMemStorage();  
    CvSeq *lines = 0;  

	cvMerge(src,src,src,NULL,src3);
	cvNamedWindow("1");
	cvShowImage("1",src);
	lines = cvHoughLines2(src,storage,CV_HOUGH_STANDARD,1,CV_PI/180,100,0,0);
	int y_median(0);
	int temp(0);
	int n_horizon(0);

	for(int i = 0; i < MIN(lines->total,100); i++ )
	{
		float* line = (float*)cvGetSeqElem(lines,i);
		float rho = line[0];
		float theta = line[1];
		CvPoint pt1, pt2;
		if(theta>1.3 && theta<1.7)
		{
			double a = cos(theta), b = sin(theta);
			double x0 = a*rho, y0 = b*rho;
			pt1.x = cvRound(x0 + 1000*(-b));
			pt1.y = cvRound(y0 + 1000*(a));
			pt2.x = cvRound(x0 - 1000*(-b));
			pt2.y = cvRound(y0 - 1000*(a));
		//	cvLine( src3, pt1, pt2, CV_RGB(255,0,0), 1, CV_AA, 0 );
			n_horizon++;
			y_median += ( (pt1.y + pt2.y)/2 );
		/*	if(y_median!=0)
				y_median = (temp + y_median)/2;
			else
				y_median = temp;*/

		}
		else
		{
			double a = cos(theta), b = sin(theta);
			double x0 = a*rho, y0 = b*rho;
			pt1.x = cvRound(x0 + 1000*(-b));
			pt1.y = cvRound(y0 + 1000*(a));
			pt2.x = cvRound(x0 - 1000*(-b));
			pt2.y = cvRound(y0 - 1000*(a));
//			cvLine( src3, pt1, pt2, CV_RGB(255,0,0), 1, CV_AA, 0 );	
		}
		printf("i = %d\n",i);
		printf("x1 = %d,y1 = %d\n",pt1.x,pt1.y);
		printf("x2 = %d,y2 = %d\n",pt2.x,pt2.y);

	}
	y_median = y_median/n_horizon;
	cvRectangle(src3,cvPoint(0,y_median+25),cvPoint(640,y_median-25),CV_RGB(0,0,0),CV_FILLED,8,0);

    cvShowImage("3",src3);
	printf("y_median = %d\n",y_median); 
	cvSaveImage("C:\\xiu.jpg",src3);

	cvWaitKey(0);


	cvDestroyWindow("1");
	cvReleaseImage(&src);
	
	return 0;
}
//if(theta>2.9 || theta<0.2) //vertical

/**

for(int i = 0; i < MIN(lines->total,100); i++ )
    {
        float* line = (float*)cvGetSeqElem(lines,i);
        float rho = line[0];
        float theta = line[1];
        CvPoint pt1, pt2;
        double a = cos(theta), b = sin(theta);
        double x0 = a*rho, y0 = b*rho;
        pt1.x = cvRound(x0 + 1000*(-b));
        pt1.y = cvRound(y0 + 1000*(a));
        pt2.x = cvRound(x0 - 1000*(-b));
        pt2.y = cvRound(y0 - 1000*(a));
        cvLine( src3, pt1, pt2, CV_RGB(255,0,0), 1, CV_AA, 0 );
		cvShowImage("3",src3);
		printf("i = %d\n",i);
		printf("x1 = %d,y1 = %d\n",pt1.x,pt1.y);
		printf("x2 = %d,y2 = %d\n",pt2.x,pt2.y);
		
	
	}
**/



3.直线方程计算

通过测试可以知道,以上代码计算出来的直线,其实是由两个坐标值超出图像显示区域的点连线而成的。

笔者在程序中需要对直线区域进行填充,使用的是cvrectangle(fill),发现在水平和垂直线上填充效果很好,但是斜线往往有蛮大偏差,不能完全覆盖直线区域。最后发现原因就是没有搞清楚以上代码中的pt1、pt2的含义。使用pt3、pt4才是我想要的效果。



所以需要利用pt1、pt2计算出直线的方程,然后推知pt3、pt4的坐标,代码修改如下:

			if(theta>1.3 && theta<1.7)   //horizon
			{  
				double a = cos(theta), b = sin(theta);  
				double x0 = a*rho, y0 = b*rho;  
				pt_1.x = cvRound(x0 + 1000*(-b));  //88
				pt_1.y = cvRound(y0 + 1000*(a));  
				pt_2.x = cvRound(x0 - 1000*(-b));  //88
				pt_2.y = cvRound(y0 - 1000*(a));  	
				double KK;
				KK = (double)(pt_1.y - pt_2.y)/(double)(pt_1.x - pt_2.x);
				int yL = cvRound( KK*(0 - pt_2.x) + pt_2.y );
				int yR = cvRound( KK*(640 - pt_2.x) + pt_2.y );
				CvPoint pt1;CvPoint pt2;CvPoint pt3;CvPoint pt4;
				pt1.x = 0;	pt1.y = yL - 25;
				pt2.x = 0;	pt2.y = yL + 25;
				pt3.x = 640;	pt3.y = yR + 25;
				pt4.x = 640;	pt4.y = yR - 25;

				fillArbitaryRectangle(temp,pt1,pt2,pt3,pt4);
				cvLine( src_original_3, pt_1, pt_2, CV_RGB(160,32,240), 1, CV_AA, 0 ); 
			}
			if(theta>2.9 || theta<0.2) //vertical
			{  
				double a = cos(theta), b = sin(theta);  
				double x0 = a*rho, y0 = b*rho;  
				pt_1.x = cvRound(x0 + 1000*(-b));  
				pt_1.y = cvRound(y0 + 1000*(a));  //888
				pt_2.x = cvRound(x0 - 1000*(-b));  
				pt_2.y = cvRound(y0 - 1000*(a));  //888
				double KK;
				KK = (double)(pt_1.x - pt_2.x)/(double)(pt_1.y - pt_2.y);
				int xT = cvRound( KK*(0 - pt_2.y) + pt_2.x );
				int xB = cvRound( KK*(480 - pt_2.y) + pt_2.x );
				CvPoint pt1;CvPoint pt2;CvPoint pt3;CvPoint pt4;
				pt1.x = xT - 25;	pt1.y = 0;
				pt2.x = xT + 25;	pt2.y = 0;
				pt3.x = xB + 25;	pt3.y = 480;
				pt4.x = xB - 25;	pt4.y = 480;
				fillArbitaryRectangle(temp,cvPoint(0,0),cvPoint(0,480),pt4,pt1);
				fillArbitaryRectangle(temp,pt2,pt3,cvPoint(640,480),cvPoint(640,0));
				cvLine( src_original_3, pt_1, pt_2, CV_RGB(160,32,240), 1, CV_AA, 0 ); 
			}
		}

其中的填充函数fillArbitaryRectangle如下:

//src 3 channels and will be filled
void CALEXDlg::fillArbitaryRectangle(IplImage* src,CvPoint pt1,CvPoint pt2,CvPoint pt3,CvPoint pt4)
{
	int arr[1];  
	arr[0] = 4;  
	CvPoint ** pt = new CvPoint*[1];  
	pt[0] = new CvPoint[4];  
	pt[0][0] = pt1;  
	pt[0][1] = pt2;  
	pt[0][2] = pt3;  
	pt[0][3] = pt4;  
	cvPolyLine( src_original_hough, pt, arr, 1, 1, CV_RGB(255,97,0));  
	cvFillPoly(src,pt,arr,1,CV_RGB(0,0,0)); 

}







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值