參考:http://www.voidcn.com/article/p-uvzxwqea-bch.html
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
Vec3b RandomColor(int value); //生成隨機顏色函數
int main(int argc, char* argv[])
{
Mat image = imread("D:\\xxxxxx\\image\\4078.png");//載入RGB彩色圖像
imshow("Source Image", image);
//灰度化,濾波,Canny邊緣檢測
Mat imageGray, imageCanny;
cvtColor(image, imageGray, CV_BGR2GRAY);//灰度轉換
GaussianBlur(imageGray, imageGray, Size(5, 5), 2); //高斯濾波
imshow("Gray Image", imageGray);
Canny(imageGray, imageCanny, 40, 100);
imshow("Canny Image", imageCanny);
//查找輪廓
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(imageCanny, contours, hierarchy, RETR_LIST, CHAIN_APPROX_SIMPLE, Point());
Mat imageContours = Mat::zeros(image.size(), CV_8UC1); //輪廓
Mat marks(image.size(), CV_32S); //Opencv分水嶺第二個矩陣參數
marks = Scalar::all(0);
int index = 0;
int compCount = 0;
for (; index >= 0; index = hierarchy[index][0], compCount++)
{
//對marks進行標記,對不同區域的輪廓進行編號,相當於設置注水點,有多少輪廓,就有多少注水點
drawContours(marks, contours, index, Scalar::all(compCount + 1), 1, 8, hierarchy);
drawContours(imageContours, contours, index, Scalar(255), 1, 8, hierarchy);
}
//我們來看一下傳入的矩陣marks裏是什麼東西
Mat marksShows;
convertScaleAbs(marks, marksShows);
imshow("marksShow", marksShows);
imshow("輪廓", imageContours);
watershed(image, marks);
//我們再來看一下分水嶺算法之後的矩陣marks裏是什麼東西
Mat afterWatershed;
convertScaleAbs(marks, afterWatershed);
imshow("After Watershed", afterWatershed);
//對每一個區域進行顏色填充
Mat PerspectiveImage = Mat::zeros(image.size(), CV_8UC3);
for (int i = 0; i < marks.rows; i++)
{
for (int j = 0; j < marks.cols; j++)
{
int index = marks.at<int>(i, j);
if (marks.at<int>(i, j) == -1)
{
PerspectiveImage.at<Vec3b>(i, j) = Vec3b(255, 255, 255);
}
else
{
PerspectiveImage.at<Vec3b>(i, j) = RandomColor(index);
}
}
}
imshow("After ColorFill", PerspectiveImage);
//分割並填充顏色的結果跟原始圖像融合
Mat wshed;
addWeighted(image, 0.4, PerspectiveImage, 0.6, 0, wshed);
imshow("AddWeighted Image", wshed);
//waitKey();
cvWaitKey(0);
return 0;
}
Vec3b RandomColor(int value) //生成隨機顏色函數
{
value = value % 255; //生成0~255的隨機數
RNG rng;
int aa = rng.uniform(0, value);
int bb = rng.uniform(0, value);
int cc = rng.uniform(0, value);
return Vec3b(aa, bb, cc);
}
原圖: 灰度: 輪廓:
Mark: 輪廓: 分水嶺:
填充顏色: