1. 泛洪填充、漫水填充
鼠标点击选择中心点进行填充(鼠标单击事件)
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
Mat src;
RNG rng(123456);
void onMouse(int event, int x, int y, int flags, void* userdata){
// 如果鼠标左键被按下,就在这里打个点开始填充
if(event == CV_EVENT_LBUTTONDOWN){
// 构建一个随机的颜色
Scalar randomColor = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
Rect rect;
// 输入图 种子点 填充颜色 输出填充大小 最小差异 最大差异 按照范围填充
floodFill(src,Point(x,y),randomColor,&rect,Scalar(20,20,20),Scalar(100,100,100),FLOODFILL_FIXED_RANGE);
cout<<rect.size()<<endl;
imshow("src",src);
}
}
int main(int argc,char** argv){
string path = "/home/kaijun/Documents/resource/opencv/zp.jpg";
// 读取图片
src = imread(path,IMREAD_COLOR);
// 定义窗口
namedWindow("src",WINDOW_NORMAL);
setMouseCallback("src",onMouse);
imshow("src",src);
waitKey(0);
return 0;
}
2. 分水岭算法
Mat markers(src.size(),CV_32S); //markers需要进一步定义
watershed(src,markers);
示例代码如下:
/**
Created by kaijun on 10/17/19.
图像分水岭
*/
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
string path = "/home/kaijun/Pictures/wan.png";
Mat src = imread(path,IMREAD_COLOR);
int n=1;
void onMouse(int event, int x, int y, int flags, void* userdata){
Mat markers = *(Mat*)userdata;
// 当鼠标左键按下的时候
if(event == EVENT_LBUTTONDOWN){
// 可视化一下markers,在markers上画圆
circle(markers,Point(x,y),50,Scalar(n++),-1);
imshow("markers",markers);
}
// 当鼠标右键按下的时候
if(event == EVENT_RBUTTONDOWN){
// 颜色列表
vector<Vec3b> colors={Vec3b(255,255,0),Vec3b(0,255,255)};
// 执行分水岭操作
watershed(src,markers);
// 定义一个用于显示结果的图像
Mat result(markers.size(),CV_8UC3);
for (int row = 0; row < markers.rows; ++row) {
for (int col = 0; col < markers.cols; ++col) {
int index = markers.at<int>(row,col);
if(index>0 && index<n){
result.at<Vec3b>(row,col) = colors[index-1];
cout<<index<<n<<endl;
}
}
}
imshow("result",result);
}
}
int main(int argc,char** argv){
// 显示原图像
imshow("src",src);
// 彩色图像转成灰度图像
Mat gray;
cvtColor(src,gray,COLOR_BGR2GRAY);
imshow("gray",gray);
// 定义用于记录标记的图像
Mat markers(src.size(),CV_32S);
// 注册鼠标滑动时间
setMouseCallback("gray",onMouse,&markers);
Mat binary;
threshold(gray,binary,0,255,THRESH_BINARY|THRESH_TRIANGLE);
imshow("binary",binary);
waitKey(0);
return 0;
}
3. 距离变换
Opencv中distanceTransform方法用于计算图像中每一个非零点距离自己最近的零点的距离,方法输出的信息为距离而不是颜色值,图像上越亮的点,代表了离零点的距离越远。
可以用来细化轮廓,或者寻找物体的质心!
void cv::distanceTransform(InputArray src, 输入图像
OutputArray dst, 输出图像
int distanceType, 计算距离的方法
int maskSize, 掩膜的大小,一般为3x3 或者 5x5
int dstType = CV_32F 选用默认值即可
// 例:距离变换
Mat distanceImg;
distanceTransform(binary,distanceImg,DIST_L2,3);
)
方法 | 原理 |
---|---|
DIST_L1 | distance = |x1-x2| + |y1-y2| |
DIST_L2 | the simple euclidean distance |
DIST_C | distance = max(|x1-x2|,|y1-y2|) |
DIST_L12 | L1-L2 metric: distance = 2(sqrt(1+x*x/2) - 1)) |
DIST_FAIR | distance = c^2(|x|/c-log(1+|x|/c)), c = 1.3998 |
DIST_WELSCH | distance = c2/2(1-exp(-(x/c)2)), c = 2.9846 |
DIST_HUBER | distance = |x|<c ? x^2/2 : c(|x|-c/2), c=1.345 |