#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
//************************************
// 漫水填充
//************************************
Mat g_srcImage, g_dstImage, g_grayImage, g_maskImage;
int g_nFillMode = 1;//漫水填充模式
int g_nLowDifference = 20, g_nUpDifference = 20;//负差最大值,正差最大值
int g_nConnectivity = 4;//标识符低八位的连通值
int g_bIsColor = true;//是否为彩色图的标识符布尔值
bool g_bUseMask = false;//是否显示掩膜窗口的布尔值
int g_nNewMaskVal = 255;//新的重新绘制的像素值
static void OnMouse(int event, int x, int y, int, void *)
{
if (event != EVENT_LBUTTONDOWN)//鼠标左键没有按下
return;
Point seed = Point(x, y);
int LowDifference = g_nFillMode == 0 ? 0 : g_nLowDifference;//空范围的漫水填充,此值设置为0,否则设为全局g_nLowDiiference;
int UpDifference = g_nFillMode == 0 ? 0 : g_nUpDifference;//空范围的漫水田中,此值设置为0,否则设为全局g_nUpDifference;
//标识符的0~7位为g_nConnectivity,8~15位为g_nNewMaskVal左移八位的值,16~23为CV_FLOODFILL_FIXED_RANGE或者0
int flags = g_nConnectivity + (g_nNewMaskVal << 8) + (g_nFillMode == 1 ? FLOODFILL_FIXED_RANGE : 0);
//随机生成bgr
int b = (unsigned)theRNG() & 255;
int g = (unsigned)theRNG() & 255;
int r = (unsigned)theRNG() & 255;
Rect ccomp;
//重绘区域像素的新值,若是彩色 Scalar(b,g,r) 不是彩色 Scalar(r*0.299 + g * 0.587 + b * 0.114)
Scalar newVal = g_bIsColor ? Scalar(b, g, r) : Scalar(r*0.299 + g * 0.587 + b * 0.114);
Mat dst = g_bIsColor ? g_dstImage : g_grayImage;//目标图的赋值
int area;
if (g_bUseMask)
{
threshold(g_maskImage, g_maskImage, 1, 128, THRESH_BINARY);
area = floodFill(dst,//原图
g_maskImage,//掩膜
seed,//漫水填充起始点
newVal,//像素点被染色的值
&ccomp,//重绘区域的最小边界矩形
Scalar(LowDifference, LowDifference, LowDifference)//像素值与其部件邻域像素值或者带加入该部件的种子像素之间的亮度或者颜色之正差的最大值
);
}
else
{
area = floodFill(dst,
seed,
newVal,
&ccomp,
Scalar(LowDifference, LowDifference, LowDifference),//像素值与其部件邻域像素值或者带加入该部件的种子像素之间的亮度或者颜色之负差的最大值
Scalar(UpDifference, UpDifference, UpDifference//像素值与其部件邻域像素值或者带加入该部件的种子像素之间的亮度或者颜色之正差的最大值
)
);
}
imshow("效果图", dst);
cout << area << "个像素值被修改\n";
}
int main()
{
system("color 5E");
g_srcImage = imread("C:/Users/hasee-pc/Desktop/dog.jpg");
if (!g_srcImage.data)
{
printf("读取图片错误\n");
return false;
}
g_srcImage.copyTo(g_dstImage);//复制源图到目标图
cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);//转换三通道的image0的灰度图
g_maskImage.create(g_srcImage.rows + 2, g_srcImage.cols + 2, CV_8UC1);//利用源图的尺寸来初始化掩膜mask
namedWindow("效果图", WINDOW_AUTOSIZE);
createTrackbar("负差最大值", "效果图", &g_nLowDifference, 255, 0);
createTrackbar("正差最大值", "效果图", &g_nUpDifference, 255, 0);
setMouseCallback("效果图", OnMouse, 0);
while (1)
{
imshow("效果图", g_bIsColor ? g_dstImage : g_grayImage);
int c = waitKey(0);
if ((c & 255) == 27)
{
cout << "程序退出。。。。。。。。。。\n";
break;
}
switch ((char)c)
{
case '1':
if (g_bIsColor)
{
cout << "键盘‘1’被按下,切换彩色/灰度模式,当前操作为将【彩色模式】切换为【灰度模式】\n";
cvtColor(g_srcImage, g_dstImage,COLOR_BGR2GRAY);
g_maskImage = Scalar::all(0);//将mask所有元素设置 为0
g_bIsColor = false;//当前图像为灰度
}
else
{
cout << "键盘‘1’被按下,切换彩色/灰度模式,当前操作为将【灰度模式】切换为【彩色模式】\n";
g_srcImage.copyTo(g_dstImage);
g_maskImage = Scalar::all(0);
g_bIsColor = true;//当前图像模式为彩色图
}
break;
case '2':
if (g_bUseMask)
{
destroyWindow("mask");
g_bUseMask = false;
}
else
{
namedWindow("mask", 0);
g_maskImage = Scalar::all(0);
imshow("mask", g_maskImage);
g_bUseMask = true;
}
break;
case '3':
cout << "按键‘3’被按下,恢复原始图像\n";
g_srcImage.copyTo(g_dstImage);
cvtColor(g_dstImage, g_grayImage, COLOR_BGR2GRAY);
g_maskImage = Scalar::all(0);
break;
case '4':
cout << "按键‘4’被按下,使用空范围的漫水填充" << endl;
g_nFillMode = 0;
break;
case '5':
cout << "按键‘5’被按下,使用渐变 固定范围的漫水填充" << endl;
g_nFillMode = 1;
break;
case '6':
cout << "按键‘6’被按下,使用渐变 浮动范围的漫水填充" << endl;
g_nFillMode = 2;
break;
case '7':
cout << "按键‘7’被按下,操作标志符的低八位使用4位的连续模式" << endl;
g_nConnectivity = 4;
break;
case '8':
cout << "按键‘8’被按下,操作标志符的低八位使用8位的连接模式" << endl;
g_nConnectivity = 8;
break;
default:
break;
}
}
}