OpenCV-13-泛洪(漫水)填充、分水岭、距离变换

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_L1distance = |x1-x2| + |y1-y2|
DIST_L2the simple euclidean distance
DIST_Cdistance = max(|x1-x2|,|y1-y2|)
DIST_L12L1-L2 metric: distance = 2(sqrt(1+x*x/2) - 1))
DIST_FAIRdistance = c^2(|x|/c-log(1+|x|/c)), c = 1.3998
DIST_WELSCHdistance = c2/2(1-exp(-(x/c)2)), c = 2.9846
DIST_HUBERdistance = |x|<c ? x^2/2 : c(|x|-c/2), c=1.345

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值