[opencv]findSquares4代码详解

CvSeq* findSquares4(IplImage* img, CvMemStorage* storage)
{
	CvSeq* contours;
	int i, c, l, N = 11;
	CvSize sz = cvSize(img->width & -2, img->height & -2);

	IplImage* timg = cvCloneImage(img);
	IplImage* gray = cvCreateImage(sz, 8, 1);
	IplImage* pyr = cvCreateImage(cvSize(sz.width / 2, sz.height / 2), 8, 3);
	IplImage* tgray;
	CvSeq* result;
	double s, t;
	// ŽŽœšÒ»žö¿ÕÐòÁÐÓÃÓڎ探ÂÖÀªœÇµã
	CvSeq* squares = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), storage);
	cvSetImageROI(timg, cvRect(0, 0, sz.width, sz.height));
	// ¹ýÂËÔëÒô
	cvPyrDown(timg, pyr, 7);
	cvPyrUp(pyr, timg, 7);
	tgray = cvCreateImage(sz, 8, 1);
	// ºìÂÌÀ¶3É«·Ö±ð³¢ÊÔÌáÈ¡
	
	for (c = 0; c < 3; c++)
	{
		// ÌáÈ¡ the c-th color plane
		cvSetImageCOI(timg, c + 1);
		cvCopy(timg, tgray, 0);
		/*if (c == 0)
			cvShowImage("gray0", tgray);
		if (c == 1)
			cvShowImage("gray1", tgray);
		if (c == 2)
			cvShowImage("gray2", tgray);*/
		// ³¢ÊÔž÷ÖÖãÐÖµÌáÈ¡µÃµœµÄ£šN=11£©
		for (l = 0; l < N; l++)
		{
			// apply Canny. Take the upper threshold from slider
			// Canny helps to catch squares with gradient shading  
			/*if (l == 0)
			{
				cvCanny(tgray, gray, 0, thresh, 5);
				//ʹÓÃÈÎÒâœá¹¹ÔªËØÅòÕÍÍŒÏñ
				cvDilate(gray, gray, 0, 1);
			}
			else
			{
				// apply threshold if l!=0:
				cvThreshold(tgray, gray, (l + 1) * 255 / N, 255, CV_THRESH_BINARY);
			}*/
			cvThreshold(tgray, gray, (l + 1) * 255 / N, 255, CV_THRESH_BINARY);
			//cvCvtColor(tgray, gray, CV_BGR2GRAY);
			// ÕÒµœËùÓÐÂÖÀª²¢ÇҎ探ÔÚÐòÁÐÖÐ
			cvFindContours(gray, storage, &contours, sizeof(CvContour),
				CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
			// ±éÀúÕÒµœµÄÿžöÂÖÀªcontours
                        int index = 0;
			while (contours)
			{
				//ÓÃÖž¶šŸ«¶È±Æœü¶à±ßÐÎÇúÏß
				result = cvApproxPoly(contours, sizeof(CvContour), storage,
					CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0);
                                //printf("betsy: total=%d , index=%d\n",result->total ,index);
                                index ++;
				if (result->total == 4 &&
					fabs(cvContourArea(result, CV_WHOLE_SEQ)) > 100 &&
					fabs(cvContourArea(result, CV_WHOLE_SEQ)) < 2000000 &&
					cvCheckContourConvexity(result))
				{
					s = 0;
					for (i = 0; i < 5; i++)
					{
						// find minimum angle between joint edges (maximum of cosine)
						if (i >= 2)
						{
							t = fabs(angle(
								(CvPoint*)cvGetSeqElem(result, i),
								(CvPoint*)cvGetSeqElem(result, i - 2),
								(CvPoint*)cvGetSeqElem(result, i - 1)));
							s = s > t ? s : t;
						}
					}
					// if ÓàÏÒÖµ ×㹻С£¬¿ÉÒÔÈ϶šœÇ¶ÈΪ90¶ÈÖ±œÇ
					//cos0.1=83¶È£¬ÄܜϺõÄÇ÷œüÖ±œÇ
					if (s > 88 && s < 92)
						for (i = 0; i < 4; i++)
							cvSeqPush(squares,
							(CvPoint*)cvGetSeqElem(result, i));
				}
				// ŒÌÐø²éÕÒÏÂÒ»žöÂÖÀª
				contours = contours->h_next;
			}
		}
	}
	cvReleaseImage(&gray);
	cvReleaseImage(&pyr);
	cvReleaseImage(&tgray);
	cvReleaseImage(&timg);
	return squares;
}

1. CvSeq* contours 创建了一个序列

2. 定义了CvSize的矩阵框大小,以像素为精度,(&-2 什么意思?)

3.IplImage* timg = cvCloneImage ,拷贝了原图用来处理(函数内部会额外分配内存,将源数据全部复制过来,包括ROI区域,使用前无需申请,在for循环中使用会消耗内存,每次用完需要用cvRelease来释放)

4.IplImage* gray = cvCreateImage(sz, 8, 1); 创建灰度图,     创建头并分配数据,宽高,位深度,通道

5.IplImage* pyr = cvCreateImage(cvSize(sz.width / 2, sz.height / 2), 8, 3); 创建1/4图大小的三通道图像

6.CvSeq* squares = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), storage) 创建序列

   cvSetImageROI(timg, cvRect(0, 0, sz.width, sz.height));    设定了ROI

   创建一个空序列用于存储轮廓角点

typedef  struct  CvPoint
{
    int x;//图像中点的x坐标
    int y;//图像中点的y坐标
}CvPoint;

7. cvPyrDown(timg, pyr, 7);
    cvPyrUp(pyr, timg, 7);

cvPyrDown/Up 使用Gaussian金字塔分解对输入图像向下/上采样 ,为了过滤噪音

8. for (c = 0; c < 3; c++) 红绿蓝3色分别尝试提取 

9.cvSetImageCOI : 设置图像的COI的函数,coi为0时表示选择所有通道,1第一通道以此类推

10.cvThreshold(tgray, gray, (l + 1) * 255 / N, 255, CV_THRESH_BINARY);

对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像。(cvCmpS 也可以达到此目的) 或者是去掉噪声,例如过滤很小或很大象素值的图像 

11.cvFindContours(gray, storage, &contours, sizeof(CvContour),
                CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));

 找到所有轮廓并存储在序列中

12.cvApproxPoly(contours, sizeof(CvContour), storage,
                    CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0);

使用多边形去逼近轮廓,使顶点数目变少

13. cvContourArea(result, CV_WHOLE_SEQ) 计算轮廓面积

14.

 

 

 

 

cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT );

角点检测算法可归纳为三类:

 

  • 基于灰度图像的角点检测
  • 基于二值图像的角点检测
  • 基于轮廓曲线的角点检测

 

 

 

normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );

该函数归一化输入数组使它的范数或者数值范围在一定的范围内。

 

  convertScaleAbs( dst_norm, dst_norm_scaled );

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值