OpenCV—漫水填充floodFill之区域信息统计
2017-10-28 23:25
501 查看
本文的主要参考为
1、官方文档OpenCV249-floodFill
2、《Learning OpenCV 3》page361-364
OpenCV中提供的直线拟合API如下:
(1)由于mask的尺寸大于原图,所以原图的坐标(x,y)对应于模板为(x+1,y+1)
(2)flag的设置包括四部分,设置方式见下面源码
实例介绍:
使用函数floodFill对原图像中的感兴趣区域进行信息统计,处理的结果如下图所示。
注意事项已经在源码中做了详细的注释,参看源码。
源码:
4000
1、官方文档OpenCV249-floodFill
2、《Learning OpenCV 3》page361-364
OpenCV中提供的直线拟合API如下:
int floodFill(InputOutputArray image, Point seedPoint, Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4 ) int floodFill(InputOutputArray image, InputOutputArray mask, Point seedPoint, Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4 )详细参数含义参见官方文档,这里提出几点注意:
(1)由于mask的尺寸大于原图,所以原图的坐标(x,y)对应于模板为(x+1,y+1)
(2)flag的设置包括四部分,设置方式见下面源码
实例介绍:
使用函数floodFill对原图像中的感兴趣区域进行信息统计,处理的结果如下图所示。
注意事项已经在源码中做了详细的注释,参看源码。
源码:
#include "opencv2/opencv.hpp" #include <iostream> #include <numeric> //std::accumulate #include <vector> // std::vector using namespace cv; using namespace std; Mat g_srcImage, g_floodFillImage, g_maskImage, g_edgeImage, g_showImage;//定义原始图、目标图、灰度图、掩模图 int g_nLowDifference = 20, g_nUpDifference = 20;//负差最大值、正差最大值 int g_nConnectivity = 8;//表示floodFill函数标识符低八位的连通值 int g_nNewMaskVal = 255;//新的重新绘制的像素值 static void onMouse( int event, int x, int y, int, void* ) { // 若鼠标左键没有按下,便返回 if( event != CV_EVENT_LBUTTONDOWN ) return; //若seed为已统计过的区域则返回 //at(i,j)等价于point(y,x),一定注意对应关系:i->y,j->x int nn = g_maskImage.at<uchar>(y+1,x+1); if (nn == 128 || nn == 255) return; Point seed = Point(x,y); //标识符的0-7位为g_nConnectivity,8-15位为g_nNewMaskVal左移8位的值 //16-23位为CV_FLOODFILL_FIXED_RANGE或者0,24-31位为CV_FLOODFILL_MASK_ONLY或者0; //下面两种写法都可以 int flags = g_nConnectivity | (g_nNewMaskVal << 8) | CV_FLOODFILL_FIXED_RANGE | CV_FLOODFILL_MASK_ONLY; //int flags = g_nConnectivity + (g_nNewMaskVal << 8) + CV_FLOODFILL_FIXED_RANGE + CV_FLOODFILL_MASK_ONLY; //定义重绘区域的最小边界矩形区域 Rect roi_rect; //掩膜灰度值为三种:0/128/256,256表示刚生成的区域,128表示之前生成的区域 threshold(g_maskImage, g_maskImage, 1, 128, CV_THRESH_BINARY); //漫水填充 int area = floodFill(g_floodFillImage, g_maskImage, seed, Scalar::all(255), &roi_rect, Scalar::all(g_nLowDifference),Scalar::all(g_nUpDifference), flags); //threshold(g_maskImage, g_edgeImage, 200, 255, CV_THRESH_BINARY); //imshow( "mask", g_maskImage ); //填充区域的统计信息 vector<uchar> roi_info; for( int i = roi_rect.y; i < roi_rect.y+roi_rect.height; ++i) { for( int j = roi_rect.x; j < roi_rect.x+roi_rect.width; ++j ) { //由于mask的尺寸大于原图,所以原图的坐标(x,y)对应于模板为(x+1,y+1) if(g_maskImage.at<uchar>(i+1,j+1)==255) { roi_info.push_back(g_floodFillImage.at<uchar>(i,j)); } } } //均值 double sum = std::accumulate(std::begin(roi_info), std::end(roi_info), 0.0); double mean = sum / roi_info.size(); //方差 double accum = 0.0; std::for_each (std::begin(roi_info), std::end(roi_info), [&](const double d) { accum += (d-mean)*(d-mean); }); double stdev = sqrt(accum/(roi_info.size()-1)); //最大值最小值 double min = *std::min_element(std::begin(roi_info), std::end(roi_info)); double max = *std::max_element(std::begin(roi_info),std::end(roi_info)); //显示统计信息 int text_x = roi_rect.x+roi_rect.width;//写字的位置 int text_y = roi_rect.y+roi_rect.height/4; int line_gap = 20;//字体行间距 char text_area[1024]; sprintf(text_area,"area:%d",area); putText(g_showImage,text_area,Point(text_x,text_y),CV_FONT_HERSHEY_COMPLEX,0.5,Scalar(0,0,255),1,8); char text_mean[1024]; sprintf(text_mean,"mean:%.2f",mean); putText(g_showImage,text_mean,Point(text_x,text_y+line_gap),CV_FONT_HERSHEY_COMPLEX,0.5,Scalar(0,0,255),1,8); char text_max[1024]; sprintf(text_max,"max:%.2f",max); putText(g_showImage,text_max,Point(text_x,text_y+line_gap*2),CV_FONT_HERSHEY_COMPLEX,0.5,Scalar(0,0,255),1,8); char text_min[1024]; sprintf(text_min,"min:%.2f",min); putText(g_showImage,text_min,Point(text_x,text_y+line_gap*3),CV_FONT_HERSHEY_COMPLEX,0.5,Scalar(0,0,255),1,8); char text_std[1024]; sprintf(text_std,"stdev:%.2f",stdev); putText(g_showImage,text_std,Point(text_x,text_y+line_gap*4),CV_FONT_HERSHEY_COMPLEX,0.5,Scalar(0,0,255),1,8); //将统计区域的边缘绘制在原图上 Canny(g_maskImage,g_edgeImage,20,60); for( int i = roi_rect.y; i < roi_rect.y+roi_rect.height; ++i) { for( int j = roi_rect.x; j < roi_rect.x+roi_rect.width; ++j ) { //由于mask的尺寸大于原图,所以原图的坐标(x,y)对应于模板为(x+1,y+1) if(g_edgeImage.at<uchar>(i+1,j+1)==255) { g_showImage.at<Vec3b>(i,j)[0]= 0; g_showImage.at<Vec3b>(i,j)[1]= 0; g_showImage.at<Vec3b>(i,j)[2]= 255; } } } //imshow("edge",g_edgeImage); imshow("效果图", g_showImage); } int main( int argc, char** argv ) { //载入原图 g_srcImage = imread("1.bmp", 0); if( !g_srcImage.data ) { printf("Oh,no,读取图片image0错误~! \n"); return false; } //拷贝源图到目标图--用于计算的图 g_srcImage.copyTo(g_floodFillImage); //构造显示的图像(仅用来显示和获取鼠标坐标,不参与计算) g_srcImage.copyTo(g_showImage); //显示的图为彩色格式,用来显示彩色的边缘和文字 cvtColor(g_showImage,g_showImage,CV_GRAY2RGB); //初始化掩膜mask g_maskImage.create(g_floodFillImage.rows+2, g_floodFillImage.cols+2, CV_8UC1); g_maskImage = Scalar::all(0); namedWindow( "效果图",CV_WINDOW_AUTOSIZE ); imshow("效果图",g_floodFillImage); //创建Trackbar createTrackbar( "负差最大值", "效果图", &g_nLowDifference, 255, 0 ); createTrackbar( "正差最大值" ,"效果图", &g_nUpDifference, 255, 0 ); //鼠标回调函数 setMouseCallback( "效果图", onMouse, 0 ); waitKey(); return 0; }
4000
相关文章推荐
- opencv FloodFill(漫水填充)和物体选取
- 水漫金山:OpenCV漫水填充算法(Floodfill)
- 11基于opencv的漫水填充算法floodFill()
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- Opencv图像识别从零到精通(24)------漫水填充,种子填充,区域生长、孔洞填充
- [转]【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- OpenCV之十五 水漫金山:OpenCV漫水填充算法(Floodfill)
- OpenCV 漫水填充算法(Floodfill)
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- opencv 漫水填充函数 floodFill 说明
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
- Opencv Python版学习笔记(二)漫水填充
- OPENCV二值化图像内孔洞填充/小区域去除