小白学视觉,笔记,扩展
#include
#include
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat img, imgGray, imgMask, img_;
Mat maskWaterShed; // watershed()函数的参数
img = imread("lenaw.png"); //含有标记的图像
img_ = imread("lena.png"); //原图像
cvtColor(img, imgGray, COLOR_BGR2GRAY);
//二值化并开运算
threshold(imgGray, imgMask, 254, 255, THRESH_BINARY);
Mat k = getStructuringElement(0, Size(3, 3));
morphologyEx(imgMask, imgMask, MORPH_OPEN, k);
imshow("含有标记的图像", img);
imshow("原图像", img_);
imshow("imgMask", imgMask);
vector> contours;
vector hierarchy;
findContours(imgMask, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
//imshow("imgMask2", imgMask);
//在maskWaterShed上绘制轮廓,用于输入分水岭算法
maskWaterShed = Mat::zeros(imgMask.size(), CV_32S);
for (int index = 0; index < contours.size(); index++)
{
drawContours(maskWaterShed, contours, index, Scalar::all(index + 1), -1, 8, hierarchy, INT_MAX);
}
//分水岭算法 需要对原图像进行处理
watershed(img_, maskWaterShed);
vector colors; // 随机生成几种颜色,生成三种颜色,对三个标记进行注水
for (int i = 0; i < contours.size(); i++)
{
int b = theRNG().uniform(0, 255);
int g = theRNG().uniform(0, 255);
int r = theRNG().uniform(0, 255);
colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
}
Mat resultImg = Mat(img.size(), CV_8UC3); //显示图像
for (int i = 0; i < imgMask.rows; i++)
{
for (int j = 0; j < imgMask.cols; j++)
{
// 绘制每个区域的颜色
int index = maskWaterShed.at(i, j);
if (index == -1) // 区域间的值被置为-1(边界)
{
resultImg.at(i, j) = Vec3b(255, 255, 255);
}
else if (index <= 0 || index > contours.size()) // 没有标记清楚的区域被置为0
{
resultImg.at(i, j) = Vec3b(0, 0, 0);
}
else // 其他每个区域的值保持不变:1,2,…,contours.size()
{
resultImg.at(i, j) = colors[index - 1]; // 把些区域绘制成不同颜色
}
}
}
imshow("resultImg", resultImg);//分割注水结果,是不含原图像信息的
resultImg = resultImg * 0.8 + img_ * 0.2;//为了便于查看,将分割结果和原图进行叠加
//addWeighted(resultImg, 0.8, img_, 0.2, 0, resultImg);
imshow("分水岭结果", resultImg);
//绘制每个区域的图像,得到每个分割区域的原图
for (int n = 1; n <= contours.size(); n++)
{
Mat resImage1 = Mat(img.size(), CV_8UC3); // 声明一个最后要显示的图像
for (int i = 0; i < imgMask.rows; i++)
{
for (int j = 0; j < imgMask.cols; j++)
{
int index = maskWaterShed.at(i, j);
if (index == n)
resImage1.at(i, j) = img_.at(i, j);
else
resImage1.at(i, j) = Vec3b(0, 0, 0);
}
}
//显示图像
imshow(to_string(n), resImage1);
}
waitKey(0);
return 0;
}
在头像上,标记3个线条,作为注水点,不断注水,最后形成这三个区域的分水岭
为了便于找到这是哪个标记,二值化、开运算、轮廓提取;
在maskWaterShed上绘制轮廓,用于输入分水岭算法;
对原图像进行处理
随机生成几种颜色,生成三种颜色,对三个标记进行注水;
区域间的值被置为-1,白色填充(边界);
没有标记清楚的区域被置为0,黑色填充;
其他每个区域的值保持不变:1,2,…,contours.size(),用生成三种颜色,对三个标记进行注水;
分割注水结果,是不含原图像信息的;
为了便于查看,将分割结果和原图进行叠加;
绘制每个区域的图像,得到每个分割区域的原图