【练习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);
时间: 2024-08-06 20:00:06

【练习5.6】漫水填充法、阈值化、cvSaveImage保存格式的相关文章

Oil Deposits DFS FloodFill漫水填充法求连通块问题

Oil Deposits The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It

Opencv3编程入门笔记(4)腐蚀、膨胀、开闭运算、漫水填充、金字塔、阈值化、霍夫变换

19      腐蚀erode.膨胀dilate 腐蚀和膨胀是针对图像中的白色部分(高亮部分)而言的,不是黑色的.除了输入输出图像外,还需传入模板算子element,opencv中有三种可以选择:矩形MORPH_RECT,交叉形MORPH_CROSS,椭圆形MORPH_ELLIPSE.Matlab中会有更多一点的模板. 例如: Mat element = getStructuringElement(MORPH_RECT,Size(15,15)); erode(srcImage,dstImage,

漫水填充

漫水填充:将与种子点相连的像素相近的连通域替换成指定颜色.如果存在mask,不会填充mask的非零像素.比如边缘检测输出图像可作为mask图 作用:1.标记或分离目标区域: 2.获取掩码区域,只处理掩码指定的像素点,加速处理过程. [第一个版本] floodFill(InputOutputArray image,1/3通道8位或浮点图像 Point seedPoint,种子点,起始点 Scalar newVal,指定颜色 Rect* rect=0,设定重绘区域的最小边界矩形 Scalar loD

[计算机图形学] 基于C#窗口的Bresenham直线扫描算法、种子填充法、扫描线填充法模拟软件设计(一)

一.首先说明: 这是啥? —— 这是利用C#FORM写的一个用来演示计算机图形学中 ①Bresenham直线扫描算法(即:连点成线):②种子填充法(即:填充多边形):③扫描线填充法 有啥用? ——  无论是连点成线还是区域填充在高级编程中基本上都提供很高效的库函数来调用.这里拿出这些算法一方面有利于大家理解那些封装的函数底层是实现:另一方面是方便嵌入式TFT屏幕底层驱动开发时借鉴的. 是啥样? ——  如下面的操作,不言而喻. 二.进入正题: 2-1.直线的扫描转换 图形的扫描转换实质就是在光栅

迷宫 填充法新思路(填充干扰路径)

#include<iostream> #include<string> using namespace std; #define n 8 int * filler=new int[n*n];//记录填充位置 int initFiller(){//初始化填充记录器 int i,j; for(i=0;i<n;i++){ for(j=0;j<n;j++){ *(filler+n*i+j)=0; } } return 0; } int * createMaze(){//初始化迷

Opencv图像识别从零到精通(24)------漫水填充,种子填充,区域生长、孔洞填充

可以说从这篇文章开始,就结束了图像识别的入门基础,来到了第二阶段的学习.在平时处理二值图像的时候,除了要进行形态学的一些操作,还有有上一节讲到的轮廓连通区域的面积周长标记等,还有一个最常见的就是孔洞的填充,opencv这里成为漫水填充,其实也可以叫种子填充,或者区域生长,基本的原理是一样的,但是应用的时候需要注意一下,种子填充用递归的办法,回溯算法,漫水填充使用堆栈,提高效率,同时还提供了一种方式是扫描行.经常用来填充孔洞,现在来具体看看. 漫水填充:也就是用一定颜色填充联通区域,通过设置可连通

floodfill 漫水填充 查找相近的像素点

核心函数:cvFloodFill 程序: 代码: #include "cv.h" #include "cxcore.h" #include "highgui.h" #include <iostream> int floodfill(int argc,char** argv) { IplImage* src=cvLoadImage("e:\\picture\\xibao.jpg"); cvNamedWindow(&q

OpenCV与EmguCV中的漫水填充

漫水填充算法,是根据选定的种子点,用一种自定义的颜色填充种子点的联通区域,通过设置可连通像素的上下限以及连通方式来达到不同的填充效果. 漫水填充经常被用来标记或分离图像的一部分以便对其进行进一步处理或分析. 所谓漫水填充,简单来说,就是自动选中了和种子点相连的区域,接着将该区域替换成指定的颜色. 漫水填充也可以用来从输入图像获取掩码区域,掩码会加速处理过程,或者只处理掩码指定的像素点. 在OpenCV中,漫水填充是填充算法中最通用的方法.且在OpenCV 2.X中,使用C++重写过的FloodF

漫水填充算法 - cvFloodFill() 实现

前言 漫水填充算法是用来标记一片区域的:设置一个种子点,然后种子点附近的相似点都被填充同一种颜色. 该算法应用性很广,比如目标识别,photoshop 的魔术棒功能等等,是填充类算法中应用最为广泛的一个算法. 漫水填充算法函数 - cvFloodFill() 函数原型: 1 void cvFloodFill ( 2 IplImage * img, // 输入图像 3 CvPoint seedPoint, // 种子点 4 CvScalar newVal, // 像素点被染色的值 5 CvScal