#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <stdio.h>
#include <cstdlib>
using namespace std;
using namespace cv;
typedef struct regioninfo
{
CvPoint Temp;
double area;
}REGIONINFO;
double FloodFillImage(IplImage * img, CvPoint st_point, CvScalar newVal);
void DiscardTheSmallRegion(IplImage * img, REGIONINFO regionNow, REGIONINFO * largerRegion, REGIONINFO * smallRegion);
int main(int argc, const char * argv[]) {
/*1.載入圖像*/
const char filename1[] = "/Users/linwang/DownLoads/Pic3.jpg";
const char filename2[] = "/Users/linwang/DownLoads/Pic4.jpg";
IplImage * Img1 = cvLoadImage(filename1,CV_LOAD_IMAGE_GRAYSCALE);
IplImage * Img2 = cvLoadImage(filename2,CV_LOAD_IMAGE_GRAYSCALE);
/*2.縮放圖像*/
double fScale = 0.1; //縮放倍數
CvSize czSize; //目標圖像尺寸
czSize.width = Img1->width * fScale;
czSize.height = Img1->height * fScale;
IplImage * New_Img1 = cvCreateImage(czSize, Img1->depth , Img1->nChannels);
cvResize(Img1, New_Img1);
IplImage * New_Img2 = cvCreateImage(czSize, Img2->depth , Img2->nChannels);
cvResize(Img2, New_Img2);
cout<<New_Img1->width<<" -> "<<New_Img1->height<<endl;
cout<<New_Img2->width<<" -> "<<New_Img2->height<<endl;
cvNamedWindow("Pic1");
cvNamedWindow("Pic2");
cvShowImage("Pic1", New_Img1);
cvShowImage("Pic2", New_Img2);
/*3.計算img1 和 img2差值的絕對值*/
IplImage * diff12 = cvCloneImage(New_Img1);
cvSetZero(diff12);
cvAbsDiff(New_Img1, New_Img2, diff12);
cvNamedWindow("ABSDIFF");
cvShowImage("ABSDIFF", diff12);
/*4.將圖像二值閾值化*/
IplImage * dst = cvCloneImage(diff12);
cvSetZero(dst);
//cvAdaptiveThreshold(diff12, dst, 255); //自適應閾值
cvThreshold(diff12, dst, 100, 255, CV_THRESH_BINARY);
cvShowImage("Binary", dst);
/*5.將圖像進行CV_MOP_OPEN操作*/
IplImage * Mop_Open = cvCloneImage(dst);
cvSetZero(Mop_Open);
cvMorphologyEx(dst, Mop_Open, NULL,NULL, CV_MOP_OPEN, 1);
cvShowImage("MOP_OPEN", Mop_Open);
/*6.漫水填充像素值爲255的點*/
REGIONINFO largerRegion, smallRegion,regionNow;
largerRegion.area = DBL_MAX;
smallRegion.area = DBL_MIN;
double areanow;
for(int i=0;i<Mop_Open->width;i++)
{
unsigned char *ptr = (uchar *)(Mop_Open->imageData + i * Mop_Open->widthStep);
for (int j=0; j<Mop_Open->height; j++)
{
if(*(ptr+j) == 255)
{
cout<<"i = "<<i <<" j = "<<j<<endl;
regionNow.Temp.x = i;
regionNow.Temp.y = j;
areanow = FloodFillImage(Mop_Open, regionNow.Temp, cvScalar(100));
regionNow.area = areanow;
DiscardTheSmallRegion(Mop_Open,regionNow, &largerRegion, &smallRegion);
}
}
}
cvFloodFill(Mop_Open, cvPoint(largerRegion.Temp.x, largerRegion.Temp.y), cvScalar(255), cvScalarAll(0.0), cvScalarAll(0.0), NULL, 8);
cvShowImage("Flood", Mop_Open);
cvWaitKey(0);
return 1;
}
/*採用漫水填充,計算填充完當前這個點後的聯通區域面積*/
double FloodFillImage(IplImage * img , CvPoint st_point, CvScalar newVal)
{
CvConnectedComp connectInfo;
/*flags 的低八位,可以設置爲4或8,這個參數控制算法連通性*/
/*參數設置爲4,填充算法只考慮水平和豎直方向相鄰點;參數設置爲8,還會包括對角線包含對角線的相鄰點*/
int flags = 8;
cvFloodFill(img, st_point,newVal,CvScalar(2.0),CvScalar(0.0),&connectInfo,flags);
return connectInfo.area;
}
/*丟棄較小的區域*/
void DiscardTheSmallRegion(IplImage * img, REGIONINFO regionNow, REGIONINFO * largerRegion, REGIONINFO * smallRegion)
{
if (regionNow.area >= largerRegion->area)
{
smallRegion->Temp.x = largerRegion->Temp.x;
smallRegion->Temp.y = largerRegion->Temp.y;
smallRegion->area = largerRegion->area;
largerRegion->Temp.x = regionNow.Temp.x;
largerRegion->Temp.y = regionNow.Temp.y;
largerRegion->area = regionNow.area;
}
else
{
smallRegion->Temp.x = regionNow.Temp.x;
smallRegion->Temp.y = regionNow.Temp.y;
smallRegion->area = regionNow.area;
}
if(smallRegion->area!=DBL_MIN)
{
cvFloodFill(img, cvPoint(smallRegion->Temp.x, smallRegion->Temp.y), cvScalar(0), cvScalarAll(0.0), cvScalarAll(0.0), NULL, 8);
}
}
漫水填充算法: