OpenCV形态学相关函数的使用测试。

其中还包含了在书上出的题目代码。有点点乱哈。。。大笑

#include "cv.h"
#include "highgui.h"

const char szTestImage[] = "D:\\cvImg\\lin.jpg";

//这2个图像是用来测试从图像中分割出变动的区域的。也就是这两张图像需要类似,但有点点不一样。目的就是找到这不一样的地方,用于视频目标跟踪。
const char szSplitImage1[] = "D:\\cvImg\\src1.jpg";
const char szSplitImage2[] = "D:\\cvImg\\src2.jpg";

//这2个图像是用来绝对值求差用的,类似上面的图像,也是有点不一样的图像,检测出不同的地方。
const char szAbsDiffImage1[] = "D:\\cvImg\\gujinlin1.jpg";
const char szAbsDiffImage2[] = "D:\\cvImg\\gujinlin2.jpg";

int main(int argc, char** argv)
{
	//原图
	IplImage* pSourceImage = cvLoadImage(szTestImage);

	//灰度图
	IplImage* pGrayscaleImage = cvCreateImage(cvGetSize(pSourceImage), 8, 1);
	cvCvtColor(pSourceImage, pGrayscaleImage, CV_RGB2GRAY);	//这两个方法都是灰度化图像
	//cvConvertImage(pSourceImage, pGrayscaleImage);		//这两个方法都是灰度化图像

	//二值图
	IplImage* pBinaryImage = cvCloneImage(pGrayscaleImage);
	cvThreshold(pBinaryImage, pBinaryImage, 128, 255, CV_THRESH_BINARY);	//二值化图像

	//自适应阈值,二值化
	IplImage* pAdaptiveBinaryImage = cvCloneImage(pGrayscaleImage);
	cvAdaptiveThreshold(pAdaptiveBinaryImage, pAdaptiveBinaryImage, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 3, 5);

	//腐蚀,膨胀可以使用非二值图,比如原图/灰度图。
	//腐蚀
	IplImage* pErodeImage = cvCloneImage(pBinaryImage);
	cvErode(pErodeImage, pErodeImage, NULL, 1);	//为NULL使用3*3核,1为迭代次数。

	//膨胀
	IplImage* pDilate = cvCloneImage(pBinaryImage);
	cvDilate(pDilate, pDilate, NULL, 1);		//为NULL使用3*3核,1为迭代次数。

	//开运算:去除小的明亮区域,并且剩余的明亮区域被隔绝,但其大小不变。
	IplImage* pOpenImage = cvCloneImage(pBinaryImage);
	cvMorphologyEx(pOpenImage, pOpenImage, NULL, NULL, CV_MOP_OPEN, 1);

	//闭运算:消除低亮度的孤立点,亮的区域连在一起,但他们基本的大小不变。
	IplImage* pCLoseImage = cvCloneImage(pBinaryImage);
	cvMorphologyEx(pCLoseImage, pCLoseImage, NULL, NULL, CV_MOP_CLOSE, 1);

	//形态梯度:应用于灰度图,在灰度值变化最剧烈的区域得到的结果数值最大。边缘以高亮区域突出。
	IplImage* pGradientImage = cvCloneImage(pGrayscaleImage);
	IplImage* pTempImage = cvCloneImage(pGradientImage);
	cvMorphologyEx(pGradientImage, pGradientImage, pTempImage, NULL, CV_MOP_GRADIENT, 1);

	//礼帽:TopHat(src) = src - open(src)
	//     如果src = dst,则cvMorphologyEx需要临时图像模版。其大小应该和src一样。否则不需要。
	//     礼帽的效果是:局部亮度极大点被分割出。
	IplImage* pTopHatImage = cvCloneImage(pGrayscaleImage);
	cvMorphologyEx(pTopHatImage, pTopHatImage, pTempImage, NULL, CV_MOP_TOPHAT, 1);

	//黑帽:BlackHat(src) = close(src) - src
	//     如果src = dst,则cvMorphologyEx需要临时图像模版。其大小应该和src一样。否则不需要。
	//     黑帽的效果是:黑色“洞”被分割出。
	IplImage* pBlackHatImage = cvCloneImage(pGrayscaleImage);
	cvMorphologyEx(pBlackHatImage, pBlackHatImage, pTempImage, NULL, CV_MOP_BLACKHAT, 1);

	//漫水填充
	IplImage* pFloodFillImage = cvCloneImage(pBinaryImage);
	cvFloodFill(pFloodFillImage, cvPoint(0, 0), CV_RGB(255, 255, 255));

	//高斯模糊,使用高斯模糊的时候允许 in place 也就是src和dst使用同一个图像。
	IplImage* pGaussImage = cvCloneImage(pSourceImage);
	cvSmooth(pGaussImage, pGaussImage, CV_GAUSSIAN, 15);

	//高斯模糊测试
	IplImage* pGaussTestImage5X5 = cvCreateImage(cvSize(500, 500), 8, 3);
	cvSet(pGaussTestImage5X5, CV_RGB(0, 0, 0));
	uchar* pMiddleData = (uchar*)pGaussTestImage5X5->imageData + pGaussTestImage5X5->width / 2 * 3 + pGaussTestImage5X5->height / 2 * pGaussTestImage5X5->widthStep;;
	pMiddleData[0] = 255;
	pMiddleData[1] = 255;
	pMiddleData[2] = 255;
	IplImage* pGaussTestImage9X9 = cvCloneImage(pGaussTestImage5X5);
	cvSmooth(pGaussTestImage5X5, pGaussTestImage5X5, CV_GAUSSIAN, 5, 5);
	cvSmooth(pGaussTestImage5X5, pGaussTestImage5X5, CV_GAUSSIAN, 5, 5);
	cvSmooth(pGaussTestImage9X9, pGaussTestImage9X9, CV_GAUSSIAN, 9, 9);
	cvSmooth(pGaussTestImage9X9, pGaussTestImage9X9, CV_GAUSSIAN, 9, 9);

	//求元素差的绝对值,也就是dst = abs(src1 - src2)
	IplImage* pSrc1Image = cvLoadImage(szAbsDiffImage1);
	IplImage* pSrc2Image = cvLoadImage(szAbsDiffImage2);
	IplImage* pDstDiffImage = cvCloneImage(pSrc1Image);
	IplImage* pCleanDiffImage = cvCloneImage(pDstDiffImage);	//腐蚀后膨胀
	IplImage* pDirtyDiffImage = cvCloneImage(pDstDiffImage);	//膨胀后腐蚀
	cvAbsDiff(pSrc1Image, pSrc2Image, pDstDiffImage);

	//先腐蚀,后膨胀
	cvErode(pDstDiffImage, pCleanDiffImage);
	cvDilate(pCleanDiffImage, pCleanDiffImage);

	//先膨胀,后腐蚀
	cvDilate(pDstDiffImage, pDirtyDiffImage);
	cvErode(pDirtyDiffImage, pDirtyDiffImage);

	//分割元素
	IplImage* pGjlSrc1Image = cvLoadImage(szSplitImage1);
	IplImage* pGjlSrc2Image = cvLoadImage(szSplitImage2);
	IplImage* pGjlSrc1GrayscaleImage = cvCreateImage(cvGetSize(pGjlSrc1Image), 8, 1);
	IplImage* pGjlSrc2GrayscaleImage = cvCreateImage(cvGetSize(pGjlSrc2Image), 8, 1);
	IplImage* pGjlDiffImage = cvCloneImage(pGjlSrc1GrayscaleImage);

	//灰度化
	cvCvtColor(pGjlSrc1Image, pGjlSrc1GrayscaleImage, CV_RGB2GRAY);
	cvCvtColor(pGjlSrc2Image, pGjlSrc2GrayscaleImage, CV_RGB2GRAY);

	//去差的绝对值
	cvAbsDiff(pGjlSrc1GrayscaleImage, pGjlSrc2GrayscaleImage, pGjlDiffImage);

	//二值图
	IplImage* pBinaryGjlImage = cvCloneImage(pGjlDiffImage);
	cvThreshold(pBinaryGjlImage, pBinaryGjlImage, 128, 255, CV_THRESH_BINARY);	//二值化图像

	//执行下开运算。
	IplImage* pGjlBinaryMopOpenImage = cvCloneImage(pBinaryGjlImage);
	cvMorphologyEx(pGjlBinaryMopOpenImage, pGjlBinaryMopOpenImage, NULL, NULL, CV_MOP_OPEN, 1);

	//自适应阈值,二值化
	IplImage* pAdaptiveBinaryGjlImage = cvCloneImage(pGjlDiffImage);
	cvAdaptiveThreshold(pAdaptiveBinaryGjlImage, pAdaptiveBinaryGjlImage, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 3, 5);
	
	//执行下开运算
	IplImage* pGjlAdaptiveBinaryMopOpenImage = cvCloneImage(pAdaptiveBinaryGjlImage);
	cvMorphologyEx(pGjlAdaptiveBinaryMopOpenImage, pGjlAdaptiveBinaryMopOpenImage, NULL, NULL, CV_MOP_OPEN, 1);

	//这里开始根据漫水填充法来统计面积最大的区域。
	CvConnectedComp comp, maxComp;
	CvPoint ptBeforeFloodFill;

	ptBeforeFloodFill.x = -1;
	ptBeforeFloodFill.y = -1;
	maxComp.area = -1;
	for (int y = 0; y < pGjlAdaptiveBinaryMopOpenImage->height; ++y)
	{
		for (int x = 0; x < pGjlAdaptiveBinaryMopOpenImage->width; ++x)
		{
			uchar* pData = (uchar*)pGjlAdaptiveBinaryMopOpenImage->imageData + x + y * pGjlAdaptiveBinaryMopOpenImage->widthStep;
			if (pData[0] == 0)
			{
				cvFloodFill(pGjlAdaptiveBinaryMopOpenImage, cvPoint(x, y), CV_RGB(100, 100, 100), 
					cvScalarAll(0), cvScalarAll(0), &comp);				

				if (maxComp.area < comp.area)
				{
					if(maxComp.area != -1)
						cvFloodFill(pGjlAdaptiveBinaryMopOpenImage, cvPoint(ptBeforeFloodFill.x, ptBeforeFloodFill.y), CV_RGB(255, 255, 255));	
				
					maxComp = comp;
					ptBeforeFloodFill.x = x;
					ptBeforeFloodFill.y = y;
					printf("max area = %.2f\n", maxComp.area);
				}
				else
				{	
					cvFloodFill(pGjlAdaptiveBinaryMopOpenImage, cvPoint(x, y), cvScalarAll(255));	
				}

				//cvShowImage("自适应然后开运算,骨精灵 - Adaptive Open", pGjlAdaptiveBinaryMopOpenImage);
				//cvWaitKey(10);
			}
		}
	}

	//边缘检测
	IplImage* pEdgesImage = cvCloneImage(pBinaryImage);
	cvCanny(pEdgesImage, pEdgesImage, 150, 100, 3);

	if (maxComp.area > 0)
	{
		cvRectangle(pGjlAdaptiveBinaryMopOpenImage, cvPoint(maxComp.rect.x, maxComp.rect.y),
			cvPoint(maxComp.rect.x + maxComp.rect.width, maxComp.rect.y + maxComp.rect.height),
			CV_RGB(0, 0, 0), 3);
	}

	//霍夫直线变换
	CvMemStorage* pMemStorage = cvCreateMemStorage();
	IplImage* pHoughtLineImage = cvCloneImage(pEdgesImage);
	CvSeq* lines = cvHoughLines2(pHoughtLineImage, pMemStorage, CV_HOUGH_PROBABILISTIC, 1, 5, 20, 50, 10);
	for (int i = 0; i < lines->total; ++i)
	{
		CvPoint* pt = (CvPoint*)cvGetSeqElem(lines, i);
		cvDrawLine(pHoughtLineImage, pt[0], pt[1], cvScalarAll(255), 3);
	}

	//霍夫圆变换 - 这下面的代码耗时太长了,所以屏蔽掉吧。
// 	IplImage* pHoughtCirclesSourceImage = cvCloneImage(pSourceImage);
// 	IplImage* pHoughtCirclesImage = cvCloneImage(pGrayscaleImage);
// 	cvSmooth(pHoughtCirclesImage, pHoughtCirclesImage, CV_GAUSSIAN, 5, 5);
// 	CvSeq* results = cvHoughCircles(pHoughtCirclesImage, pMemStorage, CV_HOUGH_GRADIENT, 2, pHoughtCirclesImage->width / 10);
// 	printf("圆个数 %d\n", results->total);
// 	for (int i = 0; i < results->total; ++i)
// 	{
// 		float* p = (float*)cvGetSeqElem(results, i);
// 		CvPoint pt = cvPoint(cvRound(p[0]), cvRound(p[1]));
// 		cvCircle(pHoughtCirclesSourceImage, pt, cvRound(p[2]), cvScalarAll(0xFF), 5);
// 		cvShowImage("霍夫圆变换 - Hought Circles", pHoughtCirclesSourceImage);
// 		cvWaitKey(300);
// 	}
	cvShowImage("二值图 - Binary", pBinaryImage);
	cvShowImage("自适应阈值 - Adaptive", pAdaptiveBinaryImage);
	cvShowImage("腐蚀 - Erode", pErodeImage);		
	cvShowImage("膨胀 - Dilate", pDilate);			
	cvShowImage("开运算 - Morphology Open", pOpenImage);	
	cvShowImage("闭运算 - Morphology Open", pCLoseImage);	
	cvShowImage("形态梯度 - Morphology Gradient", pGradientImage);
	cvShowImage("礼帽 - Top Hat", pTopHatImage);
	cvShowImage("黑帽 - Black Hat", pBlackHatImage);
	cvShowImage("漫水填充 - Flood Fill", pFloodFillImage);
	cvShowImage("高斯模糊 - Gauss Smooth", pGaussImage);
	cvShowImage("高斯模糊测试 - Gauss Smooth Test 5 X 5", pGaussTestImage5X5);	
	cvShowImage("高斯模糊测试 - Gauss Smooth Test 9 X 9", pGaussTestImage9X9);	
	cvShowImage("求原色差的绝对值 - Abs different", pDstDiffImage);
	cvShowImage("腐蚀后碰着 - Abs different", pCleanDiffImage);
	cvShowImage("膨胀后腐蚀 - Abs different", pDirtyDiffImage);
	cvShowImage("差值后的绝对值,骨精灵 - Abs Different", pGjlDiffImage);
	cvShowImage("阈值二值化过后,骨精灵 - Binary", pBinaryGjlImage);
	cvShowImage("阈值二值化后开运算,骨精灵 - Mop Open", pGjlBinaryMopOpenImage);
	cvShowImage("自适应阈值,骨精灵 - Adaptive", pAdaptiveBinaryGjlImage);
	cvShowImage("自适应然后开运算,骨精灵 - Adaptive Open", pGjlAdaptiveBinaryMopOpenImage);
	cvShowImage("边缘检测 - Canny", pEdgesImage);
	cvShowImage("霍夫直线变换 - HoughLines2", pHoughtLineImage);
//	cvShowImage("霍夫圆变换 - Hought Circles", pHoughtCirclesSourceImage);
	cvWaitKey();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值