OpenCV分水岭算法
程序员文章站
2022-05-16 11:21:32
...
#include<iostream>
#include <opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/video/tracking.hpp>
using namespace std;
using namespace cv;
/*
任务:
选择一副彩色图像,对其中前景进行初步分割(可采用任何合适的分割方式,
例如利用阈值或利用颜色信息等等,得到二值图,其中前景用白色表示,背景用黑色表示),
然后利用形态学运算得到标记图(前景、背景、不确定区域各1种标记,不确定区域标记为0),
最后利用分水岭分割算法进行分割,要求显示出原彩色图、初步分割结果(二值图)、标记图、
3种最终分割结果(边缘图、区域图、区域图与原图混合结果)
*/
class WatershedSegmenter {
private:
cv::Mat markers; // 标记图(既是输入,也是结果)
public:
// 设置标记图
void setMarkers(const cv::Mat& markerImage) {
// 转换成整数型图像
markerImage.convertTo(markers, CV_32S);
}
// 应用分水岭分割
cv::Mat process(const cv::Mat& image) {
cv::watershed(image, markers);
return markers.clone();
}
// 以图像的形式返回分割结果
cv::Mat getSegmentation() {
cv::Mat tmp;
// 所有标签值大于255的区域都赋值为255
// 标签值小于0的赋为0
markers.convertTo(tmp, CV_8U);
return tmp;
}
// 以图像的形式返回分水岭
cv::Mat getWatersheds() {
//cv::Mat tmp;
// 在转换时将每个像素p转换为255p+255
//markers.convertTo(tmp, CV_8U, 255, 255);
return markers > -1;
}
};
void main()
{
Mat image;
image = cv::imread("1.jpg");
if (image.empty())
{
cout << "读取图像失败" << endl;
exit(EXIT_FAILURE);
}
cv::imshow("Origional Image", image);
cv::Mat binary = cv::imread("bin.bmp", cv::IMREAD_GRAYSCALE);
if (binary.empty())
{
cout << "读取图像失败" << endl;
exit(EXIT_FAILURE);
}
cv::imshow("初步分割结果(二值图)", binary);
cv::Mat fg;
// 用默认结构元素腐蚀4次
cv::erode(binary, fg, cv::Mat(), cv::Point(-1, -1), 4);
// 标识不含物体的图像像素
cv::Mat bg;
// 用默认结构元素膨胀4次
cv::dilate(binary, bg, cv::Mat(), cv::Point(-1, -1), 4);
// 将背景像素设为128,阈值1-254区间均可
cv::threshold(bg, bg, 1, 128, cv::THRESH_BINARY_INV);
// 通过合并之前两幅图得到标记图像
// (前景为255,背景为128,待定为0)
cv::Mat markers = fg + bg;
cv::imshow("标记图", markers);
// 创建分水岭分割类的对象
WatershedSegmenter segmenter;
// 设置标记图像,然后执行分割过程
segmenter.setMarkers(markers);
segmenter.process(image);
cv::imshow("分割结果(边缘图)", segmenter.getWatersheds());
// 得到方便观察的分割结果(边缘像素为黑色)
cv::Mat resultForShow = segmenter.getSegmentation();
cv::imshow("分割结果(区域图)", resultForShow);
// 将分割结果与原图融合,以便于观察结果的正确性
cv::cvtColor(resultForShow, resultForShow, cv::COLOR_GRAY2BGR);
resultForShow = resultForShow * 0.5 + image * 0.5;
cv::imshow("分割结果", resultForShow);
int c = waitKey(0);
if (c == 27)
{
exit;
}
destroyAllWindows();
}
上一篇: android 对话框
下一篇: OpenCV之分水岭算法