FloodFill和掩码

来源:互联网 发布:华为软件商店 编辑:程序博客网 时间:2024/05/23 18:28

原文地址:http://blog.csdn.net/u011630458/article/details/44260119

简介

  本篇主要是介绍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掩码,则放弃对该方向的蔓延填充。


具体代码

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. #include "opencv2/imgproc/imgproc.hpp"  
  2. #include "opencv2/highgui/highgui.hpp"  
  3.    
  4. #include <iostream>  
  5.    
  6. using namespace cv;  
  7. using namespace std;  
  8.    
  9. int loDiff = 20, upDiff = 20;  
  10. Mat image0, image, mask;  
  11. int newMaskVal = 255;  
  12.    
  13. static void onMouse( int event, int x, int y, intvoid* ){  
  14.     Mat dst = image;  
  15.     Point seed = Point(x,y);  
  16.     Scalar newVal = Scalar(0, 0, 0);  
  17.     Rect ccomp;  
  18.     int lo = loDiff;  
  19.     int up = upDiff;  
  20.     int flags = 8 + (newMaskVal << 8) + CV_FLOODFILL_FIXED_RANGE;  
  21.    
  22.     floodFill(dst, mask, seed, newVal, &ccomp, Scalar(lo, lo, lo), Scalar(up, up, up), flags);  
  23.     imshow("11", dst);  
  24. }  
  25.    
  26. int main( int argc, char** argv ){  
  27.     char* filename = argv[1];  
  28.     image0 = imread(filename, 1);  
  29.     image0.copyTo(image);  
  30.    
  31.     mask.create(image0.rows+2, image0.cols+2, CV_8UC1);  
  32.     cv::rectangle(mask,cvPoint(0, 0),cvPoint(100, 100),cvScalar(255,255,255), 8);   
  33.    
  34.     namedWindow( "image", 0);  
  35.     createTrackbar( "lo_diff""image", &loDiff, 255, 0 );  
  36.     createTrackbar( "up_diff""image", &upDiff, 255, 0 );  
  37.    
  38.     imshow("11", image);  
  39.     imshow("22", mask);  
  40.     setMouseCallback("11", onMouse, 0 );  
  41.    
  42.     waitKey(0);  
  43.     return 0;  
  44. }  


代码讲解

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


效果演示

  1、原图像:                      
  2、掩码图像:                      
  3、选择天空之后的生成图像:                      



物体选取

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


具体代码

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. #include "opencv2/imgproc/imgproc.hpp"  
  2. #include "opencv2/highgui/highgui.hpp"  
  3. #include <opencv2/core/core.hpp>  
  4. #include <opencv2/core/mat.hpp>  
  5. #include <math.h>  
  6. #include <string.h>  
  7. #include <opencv/cv.h>  
  8. #include <stdio.h>  
  9. #include "xihua_2.h"  
  10.    
  11. #include <iostream>  
  12.    
  13. using namespace cv;  
  14. using namespace std;  
  15.    
  16. int loDiff = 20, upDiff = 20;  
  17. Mat image0, image, mask;  
  18. int newMaskVal = 255;  
  19. int ratio = 3;  
  20. int kernel_size = 3;  
  21. int lowThreshold = 43;  
  22.    
  23. class MorphoFeatures{  
  24.     private:  
  25.         cv::Mat cross;  
  26.         cv::Mat diamond;  
  27.         cv::Mat square;  
  28.         cv::Mat x;  
  29.    
  30.     public:  
  31.         cv::Mat getEdges(const cv::Mat &image){  
  32.             cv::Mat result;  
  33.             cv::morphologyEx(image,result,cv::MORPH_GRADIENT,cv::Mat());  
  34.             applyThreshold(result);  
  35.             return result;  
  36.         }  
  37.         void applyThreshold(cv::Mat & result){  
  38.             cv::threshold(result,result, 40,255,cv::THRESH_BINARY);  
  39.         }  
  40. };  
  41.    
  42. MorphoFeatures morpho;  
  43.    
  44. void MyResize(Mat& mat1, Mat& mat2, int width, int height){  
  45.     IplImage pI_1 = mat1, pI_2;  
  46.    
  47.     mat2 = cv::Mat(width, height, CV_8UC1, 1);  
  48.     pI_2 = mat2;  
  49.    
  50.     cvResize(&pI_1, &pI_2, 1);  
  51. }  
  52.    
  53. static void onMouse( int event, int x, int y, intvoid* ){  
  54.     Mat dst = image;  
  55.     Point seed = Point(x,y);  
  56.     Scalar newVal = Scalar(0, 0, 0);  
  57.     Rect ccomp;  
  58.     int lo = loDiff;  
  59.     int up = upDiff;  
  60.     int flags = 8 + (newMaskVal << 8) + CV_FLOODFILL_FIXED_RANGE;  
  61.    
  62.     if(event == CV_EVENT_LBUTTONDOWN){    
  63.         floodFill(dst, mask, seed, newVal, &ccomp, Scalar(lo, lo, lo), Scalar(up, up, up), flags);  
  64.         imshow("22", dst);  
  65.     }  
  66. }  
  67.    
  68. int main( int argc, char** argv ){  
  69.     char* filename = argv[1];  
  70.     image0 = imread(filename, 1);  
  71.    
  72.     if( image0.empty() ){  
  73.         cout << "Image empty. Usage: ffilldemo <image_name>\n";  
  74.         return 0;  
  75.     }  
  76.     image0.copyTo(image);  
  77.    
  78.     mask.create(image0.rows, image0.cols, CV_8UC1);  
  79.     mask = morpho.getEdges(image);  
  80.     cvtColor(mask, mask, COLOR_BGR2GRAY);  
  81.     MyResize(mask, mask, image0.rows+2, image0.cols+2);  
  82.    
  83.    
  84.     namedWindow( "image", 0);  
  85.     createTrackbar( "lo_diff""image", &loDiff, 255, 0 );  
  86.     createTrackbar( "up_diff""image", &upDiff, 255, 0 );  
  87.    
  88.     imshow("00", mask);  
  89.     imshow("11", image);  
  90.     setMouseCallback("11", onMouse, 0 );  
  91.    
  92.     waitKey(0);  
  93.     return 0;  
  94. }  


代码讲解

  很多都和前面FloodFill使用例子的代码一样,这里只讲下mask掩码相关部分。首先创造掩码图像,接着使用morpho.getEdges获取到原图像image的边沿,并保存到掩码图像中,然后更具函数FloofFill的要求,将mask图像大小调整为原图像长宽+2。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. mask.create(image0.rows, image0.cols, CV_8UC1);  
  2. mask = morpho.getEdges(image);  
  3. cvtColor(mask, mask, COLOR_BGR2GRAY);  
  4. MyResize(mask, mask, image0.rows+2, image0.cols+2);  


效果演示

  1、原图像:                      
  2、掩码图像:                      
  3、选择花盆之后的生成图像:                      

0 0
原创粉丝点击