【练习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 }

 

结果图片:

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

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

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

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

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

要言妙道:

1     char *    saveName = "E:\Testing\Image\SavePath\image_close.PNG";
2     int  params = 0;
3     cvSaveImage(saveName, dirtydiff, &params);
原文地址:https://www.cnblogs.com/tingshuixuan2012/p/4451917.html