您的位置:首页 > 运维架构

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

2013-07-09 22:11 344 查看
其中还包含了在书上出的题目代码。有点点乱哈。。。


#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  形态学