若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/104891183
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)
上一篇:《OpenCV开发笔记(三十二):红胖子8分钟带你深入了解半阈值化(图文并貌+浅显易懂+程序源码)》
下一篇:《OpenCV开发笔记(三十四):红胖子带你傻瓜式编译Qt+openCV3.4.1+opencv_contrib(全网最浅显易懂)》
红胖子来也!!!
今天来说说漫水填充,顾名思义,漫水填充就是放水,水漫上去,那么连通的区域不就都有水,就形成了一片漫水的区域,该区域就是要分离的。
通俗一点:漫水的整个过程,首先要选择一点作为防水点,然后开始放水,放水多少就能向外围扩散多大面积,可以把像素的bgr值想象成高度,谁放的越多,能覆盖的相邻高度差就越大。
漫水填充是一种用特定的颜色填充连通区域,通过设置可联通像素的上下限以及联通方式来达到不同的填充效果的方法。它是在很多图形绘软件中常用的填充算法。
漫水填充被用来标记或分离图像的一部分,以便对其进行一步处理或分析,也可以用来从输入图像获取掩码区域,掩码会加速处理过程,或只处理掩码指定的像素点,操作的结果总是某个连续的区域。
漫水填充的原理简单来说,就是从一个点开始水漫(放水,像素rgb的差理解为高度差)附近像素点,填充成新的颜色,直到封闭区域内的所有像素点都被填充成新颜色位置。
漫水填充的实现方法也有多种:4邻域像素填充法、8邻域像素填充法、基于扫描线的填充方法。
(注意:下面的函数不带掩码输入)
CV_EXPORTS_W int floodFill( InputOutputArray image,
Point seedPoint,
Scalar newVal,
CV_OUT Rect* rect=0,
Scalar loDiff = Scalar(),
Scalar upDiff = Scalar(),
int flags = 4 );
(注意:下面的函数带掩码输入)
CV_EXPORTS_W int floodFill( InputOutputArray image,
InputOutputArray mask,
Point seedPoint,
Scalar newVal,
CV_OUT Rect* rect=0,
Scalar loDiff = Scalar(),
Scalar upDiff = Scalar(),
int flags = 4 );
void OpenCVManager::testDiffuseFill()
{
QString fileName1 = "I:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/11.jpg";
cv::Mat srcMat = cv::imread(fileName1.toStdString());
int width = 300;
int height = 200;
cv::resize(srcMat, srcMat, cv::Size(width, height));
cv::String windowName = _windowTitle.toStdString();
cvui::init(windowName);
cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 3, srcMat.rows * 4),
srcMat.type());
int x = 100;
int y = 100;
int b = 255;
int g = 0;
int r = 0;
int loB = 5;
int loG = 5;
int loR = 5;
int upB = 5;
int upG = 5;
int upR = 5;
while(true)
{
windowMat = cv::Scalar(0, 0, 0);
// 原图先copy到左边
cv::Mat leftMat = windowMat(cv::Range(0, srcMat.rows),
cv::Range(0, srcMat.cols));
cv::addWeighted(leftMat, 1.0f, srcMat, 1.0f, 0.0f, leftMat);
// 选取原图坐标点
cvui::printf(windowMat, width * 1 + 50, 30 + height * 0, "x");
cvui::trackbar(windowMat, width * 1 + 50, 40 + height * 0, 200, &x, 0, width);
cvui::printf(windowMat, width * 1 + 50, 90 + height * 0, "y");
cvui::trackbar(windowMat, width * 1 + 50, 100 + height * 0, 200, &y, 0, height);
// 修改的新颜色
cvui::printf(windowMat, width * 2 + 50, 0 + height * 0, "b");
cvui::trackbar(windowMat, width * 2 + 50, 10 + height * 0, 200, &b, 0, 255);
cvui::printf(windowMat, width * 2 + 50, 60 + height * 0, "g");
cvui::trackbar(windowMat, width * 2 + 50, 70 + height * 0, 200, &g, 0, 255);
cvui::printf(windowMat, width * 2 + 50, 120 + height * 0, "r");
cvui::trackbar(windowMat, width * 2 + 50, 130 + height * 0, 200, &r, 0, 255);
// 低像素差
cvui::printf(windowMat, width * 1 + 50, 0 + height * 1, "loB");
cvui::trackbar(windowMat, width * 1 + 50, 10 + height * 1, 200, &loB, 0, 255);
cvui::printf(windowMat, width * 1 + 50, 60 + height * 1, "loG");
cvui::trackbar(windowMat, width * 1 + 50, 70 + height * 1, 200, &loG, 0, 255);
cvui::printf(windowMat, width * 1 + 50, 120 + height * 1, "loR");
cvui::trackbar(windowMat, width * 1 + 50, 130 + height * 1, 200, &loR, 0, 255);
// 高像素差
cvui::printf(windowMat, width * 2 + 50, 0 + height * 1, "upB");
cvui::trackbar(windowMat, width * 2 + 50, 10 + height * 1, 200, &upB, 0, 255);
cvui::printf(windowMat, width * 2 + 50, 60 + height * 1, "upG");
cvui::trackbar(windowMat, width * 2 + 50, 70 + height * 1, 200, &upG, 0, 255);
cvui::printf(windowMat, width * 2 + 50, 120 + height * 1, "upR");
cvui::trackbar(windowMat, width * 2 + 50, 130 + height * 1, 200, &upR, 0, 255);
// 标志
cvui::printf(windowMat, width * 0 + 50, 60 + height * 2, "flags: default");
cvui::printf(windowMat, width * 1 + 50, 60 + height * 2, "flags: 4 | FLOODFILL_FIXED_RANGE");
cvui::printf(windowMat, width * 2 + 50, 60 + height * 2, "flags: 8 | FLOODFILL_FIXED_RANGE");
// circle
cv::circle(windowMat, cv::Point(x, y), 5, cv::Scalar(0, 0, 255), -1);
{
cv::Rect rect;
cv::Mat tempMat;
cv::Mat dstMat;
// 填充
tempMat = srcMat.clone();
cv::floodFill(tempMat,
cv::Point(x, y),
cv::Scalar(b, g, r),
&rect,
cv::Scalar(loB, loG, loR),
cv::Scalar(upB, upG, upR));
dstMat = windowMat(cv::Range(srcMat.rows * 3, srcMat.rows * 4),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::addWeighted(dstMat, 0.0f, tempMat, 1.0f, 0.0f, dstMat);
// 填充
tempMat = srcMat.clone();
cv::floodFill(tempMat,
cv::Point(x, y),
cv::Scalar(b, g, r),
&rect,
cv::Scalar(loB, loG, loR),
cv::Scalar(upB, upG, upR),
4 | cv::FLOODFILL_FIXED_RANGE);
dstMat = windowMat(cv::Range(srcMat.rows * 3, srcMat.rows * 4),
cv::Range(srcMat.cols * 1, srcMat.cols * 2));
cv::addWeighted(dstMat, 0.0f, tempMat, 1.0f, 0.0f, dstMat);
// 填充
tempMat = srcMat.clone();
cv::floodFill(tempMat,
cv::Point(x, y),
cv::Scalar(b, g, r),
&rect,
cv::Scalar(loB, loG, loR),
cv::Scalar(upB, upG, upR),
8 | cv::FLOODFILL_FIXED_RANGE);
dstMat = windowMat(cv::Range(srcMat.rows * 3, srcMat.rows * 4),
cv::Range(srcMat.cols * 2, srcMat.cols * 3));
cv::addWeighted(dstMat, 0.0f, tempMat, 1.0f, 0.0f, dstMat);
}
// 更新
cvui::update();
// 显示
cv::imshow(windowName, windowMat);
// esc键退出
if(cv::waitKey(25) == 27)
{
break;
}
}
}
对应版本号v1.28.0
上一篇:《OpenCV开发笔记(三十二):红胖子8分钟带你深入了解半阈值化(图文并貌+浅显易懂+程序源码)》
下一篇:《OpenCV开发笔记(三十四):红胖子带你傻瓜式编译Qt+openCV3.4.1+opencv_contrib(全网最浅显易懂)》
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/104891183