opencv FloodFill(漫水填充)和物体选取

简介  本篇主要是介绍opencv的FloodFill(漫水填充)和基于它实现的物体选取。FloodFill使用FloodFill函数  C++: int floodFill(InputOutputArray image, InputOutputArray mask,Point seedPoint, Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4 );  InputOutputArray:输入和输出图像。  mask:输入的掩码图像。  seedPoint:算法开始处理的开始位置。   newVal:图像中所有被算法选中的点,都用这个数值来填充。rect:最小包围矩阵。  loDiff:最大的低亮度之间的差异。upDiff:最大的高亮度之间的差异。  flag:选择算法连接方式。  简单的说,就是选中点seedPoint,然后选取出它周围和它色彩差异不大的点,并将它们的值改为newVal。如果被选取的点,遇到mask掩码,则放弃对该方向的蔓延填充。具体代码

#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp" #include <iostream> using namespace cv;using namespace std; int loDiff = 20, upDiff = 20;Mat image0, image, mask;int newMaskVal = 255; static void onMouse( int event, int x, int y, int, void* ){Mat dst = image;Point seed = Point(x,y);Scalar newVal = Scalar(0, 0, 0);Rect ccomp;int lo = loDiff;int up = upDiff;int flags = 8 + (newMaskVal << 8) + CV_FLOODFILL_FIXED_RANGE; floodFill(dst, mask, seed, newVal, &ccomp, Scalar(lo, lo, lo), Scalar(up, up, up), flags);imshow("11", dst);} int main( int argc, char** argv ){char* filename = argv[1];image0 = imread(filename, 1);image0.copyTo(image); mask.create(image0.rows+2, image0.cols+2, CV_8UC1);cv::rectangle(mask,cvPoint(0, 0),cvPoint(100, 100),cvScalar(255,255,255), 8);namedWindow( "image", 0);createTrackbar( "lo_diff", "image", &loDiff, 255, 0 );createTrackbar( "up_diff", "image", &upDiff, 255, 0 ); imshow("11", image);imshow("22", mask);setMouseCallback("11", onMouse, 0 ); waitKey(0);return 0;}

代码讲解  1、装载需要被处理的图片到image0,接着复制图片信息到image。char* filename = argv[1];image0 = imread(filename, 1);image0.copyTo(image);  2、设置掩码,,注意掩码大小需要是图片长宽+2。接着框选了一个矩形的掩码区域。mask.create(image0.rows+2, image0.cols+2, CV_8UC1);cv::rectangle(mask,cvPoint(0, 0),cvPoint(100, 100),cvScalar(255,255,255), 8);   3、设置了两个Trackbar,用来可以动态设置loDiff和upDiff的大小。namedWindow( "image", 0);createTrackbar( "lo_diff", "image", &loDiff, 255, 0 );createTrackbar( "up_diff", "image", &upDiff, 255, 0 );  4、显示原图像和掩码图像,同时注册了mouse处理函数。imshow("11", image);imshow("22", mask);setMouseCallback("11", onMouse, 0 );  5、鼠标选取参考点,设置floodFill使用动态蔓延的8连通算法,显示出被floodFill处理后图片。static void onMouse( int event, int x, int y, int, void* ){Mat dst = image;Point seed = Point(x,y);Scalar newVal = Scalar(0, 0, 0);Rect ccomp;int lo = loDiff;int up = upDiff;int flags = 8 + (newMaskVal << 8) + CV_FLOODFILL_FIXED_RANGE; floodFill(dst, mask, seed, newVal, &ccomp, Scalar(lo, lo, lo), Scalar(up, up, up), flags);imshow("11", dst);}效果演示  1、原图像:

  2、掩码图像:

  3、选择天空之后的生成图像:

物体选取

  所谓的物体选取,就是首先探测出图像的边沿,然后用边沿作为掩码,接着用FloodFill来处理选择选取的点。

具体代码

#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include <opencv2/core/core.hpp>#include <opencv2/core/mat.hpp>#include <math.h>#include <string.h>#include <opencv/cv.h>#include <stdio.h>#include "xihua_2.h" #include <iostream> using namespace cv;using namespace std; int loDiff = 20, upDiff = 20;Mat image0, image, mask;int newMaskVal = 255;int ratio = 3;int kernel_size = 3;int lowThreshold = 43; class MorphoFeatures{private:cv::Mat cross;cv::Mat diamond;cv::Mat square;cv::Mat x; public:cv::Mat getEdges(const cv::Mat &image){cv::Mat result;cv::morphologyEx(image,result,cv::MORPH_GRADIENT,cv::Mat());applyThreshold(result);return result;}void applyThreshold(cv::Mat & result){cv::threshold(result,result, 40,255,cv::THRESH_BINARY);}}; MorphoFeatures morpho; void MyResize(Mat& mat1, Mat& mat2, int width, int height){IplImage pI_1 = mat1, pI_2; mat2 = cv::Mat(width, height, CV_8UC1, 1);pI_2 = mat2; cvResize(&pI_1, &pI_2, 1);} static void onMouse( int event, int x, int y, int, void* ){Mat dst = image;Point seed = Point(x,y);Scalar newVal = Scalar(0, 0, 0);Rect ccomp;int lo = loDiff;int up = upDiff;int flags = 8 + (newMaskVal << 8) + CV_FLOODFILL_FIXED_RANGE; if(event == CV_EVENT_LBUTTONDOWN){floodFill(dst, mask, seed, newVal, &ccomp, Scalar(lo, lo, lo), Scalar(up, up, up), flags);imshow("22", dst);}} int main( int argc, char** argv ){char* filename = argv[1];image0 = imread(filename, 1); if( image0.empty() ){cout << "Image empty. Usage: ffilldemo <image_name>\n";return 0;}image0.copyTo(image); mask.create(image0.rows, image0.cols, CV_8UC1);mask = morpho.getEdges(image);cvtColor(mask, mask, COLOR_BGR2GRAY);MyResize(mask, mask, image0.rows+2, image0.cols+2);namedWindow( "image", 0);createTrackbar( "lo_diff", "image", &loDiff, 255, 0 );createTrackbar( "up_diff", "image", &upDiff, 255, 0 ); imshow("00", mask);imshow("11", image);setMouseCallback("11", onMouse, 0 ); waitKey(0);return 0;}

代码讲解  很多都和前面FloodFill使用例子的代码一样,这里只讲下mask掩码相关部分。首先创造掩码图像,接着使用morpho.getEdges获取到原图像image的边沿,并保存到掩码图像中,然后更具函数FloofFill的要求,将mask图像大小调整为原图像长宽+2。mask.create(image0.rows, image0.cols, CV_8UC1);mask = morpho.getEdges(image);cvtColor(mask, mask, COLOR_BGR2GRAY);MyResize(mask, mask, image0.rows+2, image0.cols+2);效果演示  1、原图像:

  2、掩码图像:

  3、选择花盆之后的生成图像:

却不去主动改变,而是放任它的生活态度。

opencv FloodFill(漫水填充)和物体选取

相关文章:

你感兴趣的文章:

标签云: