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、选择花盆之后的生成图像:
                      
  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值