您的位置:首页 > 其它

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

2015-04-23 21:57 495 查看
提纲

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

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

程序代码:

// OpenCVExerciseTesting.cpp : 定义控制台应用程序的入口点。
//
//D:\\Work\\Work_Programming\\Source\\Image\\lena.jpg

#include "stdafx.h"
#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace cv;
using namespace std;

struct regionInfo
{
int x;
int y;
double area;
};

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

double FloodFillImage(IplImage * img, int x, int y, CvScalar newVal);
void DiscardTheSmallRegion(IplImage * img, regionInfo regionNow, regionInfo * largerRegion, regionInfo * smallRegion);

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

int _tmain(int argc, _TCHAR* argv[])
{
regionInfo largerRegion, smallRegion,regionNow;
largerRegion.area = DBL_MIN;
smallRegion.area = DBL_MAX;

const char * fileName1 = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第5章\\ExerciseResult_5-5.jpg";
IplImage * src1 = cvLoadImage(fileName1, CV_LOAD_IMAGE_GRAYSCALE);
assert(src1);

cvNamedWindow("原始图像", 0);
cvNamedWindow("题目_a", 0);

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

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

IplImage * imgCopy = cvCloneImage(src1);
//cvZero(diff12);
//如果不用cvThreshold函数,得到的结果不是预期的,因为图片中有一部分像素值大于0但小y于255
//原本这张上一题保存的图片是阈值化过的,但保存后失真了,使用cvSaveImage的PNG格式的非压缩模式可以避免这个问题
cvThreshold(src1, imgCopy, 100, 255, CV_THRESH_BINARY);

int x = -1;
int y = -1;
double areaNow;
for (int h = 0; h < imgCopy->height;++h)
{
uchar* ptr = (uchar*)(imgCopy->imageData + h * imgCopy->widthStep);
for (int w = 0; w < imgCopy->width; ++w)
{
if (imgCopy->nChannels == 1)
{
if (ptr[w] == 255)
{
//起初将w赋值给了y,将h赋值给了x,导致结果不是自己想要的,此类问题很难找
x = w;
y = h;
areaNow = FloodFillImage(imgCopy, x, y, cvScalar(100));

regionNow.x = x;
regionNow.y = y;
regionNow.area = areaNow;

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

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

cvShowImage("题目_a", imgCopy);

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

cvWaitKey(0);

cvReleaseImage(&src1);
cvReleaseImage(&imgCopy);

cvDestroyWindow("原始图像");
cvDestroyWindow("题目_a");

return 0;
}

double FloodFillImage(IplImage * img,int x,int y,CvScalar newVal)
{
CvConnectedComp connectInfo;
int flags = 8;
cvFloodFill(img, cvPoint(x, y), newVal, cvScalarAll(2.0), cvScalarAll(0.0), &connectInfo, flags);
return connectInfo.area;
}

void DiscardTheSmallRegion(IplImage * img ,regionInfo regionNow, regionInfo * largerRegion, regionInfo * smallRegion)
{
if (regionNow.area >= largerRegion->area)
{
smallRegion->x = largerRegion->x;
smallRegion->y = largerRegion->y;
smallRegion->area = largerRegion->area;

largerRegion->x = regionNow.x;
largerRegion->y = regionNow.y;
largerRegion->area = regionNow.area;
}
else
{
smallRegion->x = regionNow.x;
smallRegion->y = regionNow.y;
smallRegion->area = regionNow.area;
}

if (smallRegion->area != DBL_MIN)
{
//FloodFillImage(img, smallRegion->x, smallRegion->y, cvScalar(0));
cvFloodFill(img, cvPoint(smallRegion->x, smallRegion->y), cvScalar(0), cvScalarAll(0.0), cvScalarAll(0.0), NULL, 8);
}
}


结果图片:



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

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

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

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

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


要言妙道:

char *    saveName = "E:\\Testing\\Image\\SavePath\\image_close.PNG";
int  params = 0;
cvSaveImage(saveName, dirtydiff, ¶ms);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: