【练习5.6】漫水填充法、阈值化、cvSaveImage保存格式

 

提纲
题目要求
程序代码
结果图片
要言妙道

 

 

 

  

 

题目要求:

 从噪声图像中创建一个清晰的掩码。完成练习5后,保留图形中最大的图形区域。在图像的左上角设置一个指针,然后让他遍历图像。当你发现像素值为255的时候,存储其位置,然后对其漫水填充,新颜色值为100,。读出漫水填充法返回的连续区域,记录下其面积。如果图像中有另一个较大的区域,那么用0值对这个相对较小的区域进行颜色填充,然后删除已记录的面积。如果新的区域大于之前的区域,那么以0值填充之前的区域并删除他的位置。最后以颜色值255填充剩余的最大区域,显示结果。现在得到一个掩码,它是唯一的连续区域。

 

程序代码:

 

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

  2 //

  3 //D:\\Work\\Work_Programming\\Source\\Image\\lena.jpg

  4 

  5 

  6 #include "stdafx.h"

  7 #include <cv.h>

  8 #include <highgui.h>

  9 #include <iostream>

 10 using namespace cv;

 11 using namespace std;

 12 

 13 struct regionInfo

 14 {

 15     int x;

 16     int y;

 17     double area;

 18 };

 19 

 20 //函数声明-->--->-->--->-->--->-->--->//

 21 

 22 double FloodFillImage(IplImage * img, int x, int y, CvScalar newVal);

 23 void DiscardTheSmallRegion(IplImage * img, regionInfo regionNow, regionInfo * largerRegion, regionInfo * smallRegion);

 24 

 25 //<--<--<--<--<--<--<--<--<--函数声明//

 26 

 27 

 28 int _tmain(int argc, _TCHAR* argv[])

 29 {

 30     regionInfo largerRegion, smallRegion,regionNow;

 31     largerRegion.area = DBL_MIN;

 32     smallRegion.area = DBL_MAX;

 33 

 34     const char * fileName1 = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第5章\\ExerciseResult_5-5.jpg";

 35     IplImage * src1 = cvLoadImage(fileName1, CV_LOAD_IMAGE_GRAYSCALE);

 36     assert(src1);

 37 

 38      

 39     cvNamedWindow("原始图像", 0);    

 40     cvNamedWindow("题目_a", 0);

 41 

 42     cvShowImage("原始图像", src1);

 43      

 44     //---------------------------a:开始--------------------------------//

 45 

 46     IplImage * imgCopy = cvCloneImage(src1);

 47     //cvZero(diff12);

 48     //如果不用cvThreshold函数,得到的结果不是预期的,因为图片中有一部分像素值大于0但小y于255

 49     //原本这张上一题保存的图片是阈值化过的,但保存后失真了,使用cvSaveImage的PNG格式的非压缩模式可以避免这个问题

 50     cvThreshold(src1, imgCopy, 100, 255, CV_THRESH_BINARY);

 51 

 52     int x = -1;

 53     int y = -1;

 54     double areaNow;

 55     for (int h = 0; h < imgCopy->height;++h)

 56     {

 57         uchar* ptr = (uchar*)(imgCopy->imageData + h * imgCopy->widthStep);

 58         for (int w = 0; w < imgCopy->width; ++w)

 59         {

 60             if (imgCopy->nChannels == 1)

 61             {

 62                 if (ptr[w] == 255)

 63                 {

 64                     //起初将w赋值给了y,将h赋值给了x,导致结果不是自己想要的,此类问题很难找

 65                     x = w;

 66                     y = h;

 67                     areaNow = FloodFillImage(imgCopy, x, y, cvScalar(100));

 68 

 69                     regionNow.x = x;

 70                     regionNow.y = y;

 71                     regionNow.area = areaNow;

 72 

 73                     DiscardTheSmallRegion(imgCopy,regionNow, &largerRegion, &smallRegion);

 74                 }

 75             }

 76         }

 77     }

 78 

 79     cvFloodFill(imgCopy, cvPoint(largerRegion.x, largerRegion.y), cvScalar(255), cvScalarAll(0.0), cvScalarAll(0.0),  NULL, 8);

 80 

 81     cvShowImage("题目_a", imgCopy);

 82 

 83 

 84     //---------------------------a:结束--------------------------------//    

 85 

 86     cvWaitKey(0);

 87 

 88     cvReleaseImage(&src1);

 89     cvReleaseImage(&imgCopy);

 90 

 91     cvDestroyWindow("原始图像");     

 92     cvDestroyWindow("题目_a");

 93 

 94     return 0;

 95 }

 96  

 97 double FloodFillImage(IplImage * img,int x,int y,CvScalar newVal)

 98 {

 99     CvConnectedComp connectInfo;

100     int flags = 8;

101     cvFloodFill(img, cvPoint(x, y), newVal, cvScalarAll(2.0), cvScalarAll(0.0), &connectInfo, flags);

102     return connectInfo.area;

103 }

104 

105 void DiscardTheSmallRegion(IplImage * img ,regionInfo regionNow, regionInfo * largerRegion, regionInfo * smallRegion)

106 {

107     if (regionNow.area >= largerRegion->area)

108     {

109         smallRegion->x = largerRegion->x;

110         smallRegion->y = largerRegion->y;

111         smallRegion->area = largerRegion->area;

112 

113         largerRegion->x = regionNow.x;

114         largerRegion->y = regionNow.y;

115         largerRegion->area = regionNow.area;    

116     }

117     else

118     {

119         smallRegion->x = regionNow.x;

120         smallRegion->y = regionNow.y;

121         smallRegion->area = regionNow.area;

122     }

123 

124     if (smallRegion->area != DBL_MIN)

125     {

126         //FloodFillImage(img, smallRegion->x, smallRegion->y, cvScalar(0));

127         cvFloodFill(img, cvPoint(smallRegion->x, smallRegion->y), cvScalar(0), cvScalarAll(0.0), cvScalarAll(0.0), NULL, 8);

128     }

129 }

 

结果图片:

【练习5.6】漫水填充法、阈值化、cvSaveImage保存格式 【练习5.6】漫水填充法、阈值化、cvSaveImage保存格式

因上一题保存图片时,使用jpg格式,而且cvSaveImage

的第三个参数使用的默认值,导致保存图片失真,

像素值除了0和255外还有其它,于是,得到的是右侧的

错误图片,漫水填充前重新阈值华或者上题保存时使用

非压缩方式可以避免此问题,保存图片的代码见后文

【练习5.6】漫水填充法、阈值化、cvSaveImage保存格式

 

要言妙道:

1     char *    saveName = "E:\\Testing\\Image\\SavePath\\image_close.PNG";

2     int  params = 0;

3     cvSaveImage(saveName, dirtydiff, &params);

 

你可能感兴趣的:(image)