任務
圈出小圓點,不能圈不規則白點
參考知識
http://blog.csdn.net/qq_16540387/article/details/78844965
http://blog.csdn.net/qq_16540387/article/details/78843936
源碼
//------------------------------------------------------------------------------------------------
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
#define WINDOW_NAME "【程序窗口】" //爲窗口標題定義的宏
double area;//輪廓面積
int g_nThresholdValue = 131;//二值化閾值
int g_nThresholdType = 3;
double minarea = 378;//目標輪廓最小像素點個數
double maxarea = 478;//目標輪廓最大像素點個數
Moments mom; // 輪廓矩
Mat image, gray, edge, dst, g_srcImage1, dst1,g_srcImage,g_grayImage,g_dstImage;
vector<vector<Point> > contours; //輪廓數組
vector<Point2d> centers; //輪廓質心座標
vector<vector<Point> >::iterator itr; //輪廓迭代器
vector<Point2d>::iterator itrc; //質心座標迭代器
vector<vector<Point> > con; //當前輪廓
Point2d center;//質心座標
void on_Threshold(int, void*);//回調函數
int main()
{
//【1】讀入源圖片
g_srcImage = imread("pos71_run7_img190.jpg");
//resize(g_srcImage, g_srcImage1, Size(g_srcImage.cols / 4, g_srcImage.rows / 4), 0, 0, INTER_LINEAR);
//imshow("原始圖", g_srcImage1);
cvtColor(g_srcImage, g_grayImage, COLOR_RGB2GRAY);//灰度轉換
namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);
createTrackbar("模式",
WINDOW_NAME, &g_nThresholdType,//二值化模式
4, on_Threshold);
createTrackbar("參數值",
WINDOW_NAME, &g_nThresholdValue,//二值化閾值
255, on_Threshold);
on_Threshold(0, 0);//滑動條回調函數
while (1)
{
int key;
key = waitKey(20);
if ((char)key == 27){ break; }
}
}
void on_Threshold(int, void*)
{
//調用閾值函數
threshold(g_grayImage, g_dstImage, g_nThresholdValue, 255, CV_THRESH_BINARY);
//resize(g_dstImage, g_srcImage1, Size(g_dstImage.cols / 4, g_dstImage.rows / 4), 0, 0, INTER_LINEAR);
//imshow("threshold", g_srcImage1);
Mat element2 = getStructuringElement(MORPH_RECT, Size(10, 10));//膨脹模板
Mat erode1, erode2;
dilate(g_dstImage, erode1, element2);//膨脹
dilate(erode1, erode2, element2);
//resize(erode2, g_srcImage1, Size(erode2.cols / 4, erode2.rows / 4), 0, 0, INTER_LINEAR);
//imshow("dilate", g_srcImage1);
findContours(erode2, contours,
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);//找出輪廓
itr = contours.begin(); //使用迭代器去除非目標輪廓
while (itr != contours.end())
{
area = contourArea(*itr);//計算面積
if ((area<minarea) | (area>maxarea))
{
itr = contours.erase(itr); //刪除
}
else
{
itr++;
}
}
dst = Mat::zeros(erode2.rows, erode2.cols, CV_8UC3);//保存中間結果
itr = contours.begin();
while (itr != contours.end())
{
area = contourArea(*itr);
con.push_back(*itr);
//cout << "\nb " << area;
drawContours(dst, con, -1, Scalar(255, 0, 0), 2); //目標區域藍色繪製
mom = moments(*itr); //計算質心
center.x = (int)(mom.m10 / mom.m00);
center.y = (int)(mom.m01 / mom.m00);
char tam[10000];
char sam[10000];
sprintf(tam, "(%0.0f)", area);
sprintf(sam, "(%0.0f,%0.0f)", center.x, center.y);
putText(dst, tam, Point(center.x, center.y), FONT_HERSHEY_SIMPLEX, 2, Scalar(255, 0, 0), 5);//標出面積
putText(dst, sam, Point(center.x, center.y + 80), FONT_HERSHEY_SIMPLEX, 2, Scalar(0, 255, 0), 5);//標出質心
//imwrite("20003.jpg", dst);
//resize(dst, dst1, Size(dst.cols / 4, dst.rows / 4), 0, 0, INTER_LINEAR);
//imshow("中間結果", dst1);
circle(g_srcImage, Point(center.x, center.y), 5, Scalar(0, 225, 0), 2, 3);//畫圓
con.pop_back();
itr++;
}
resize(g_srcImage, g_srcImage1, Size(g_srcImage.cols / 4, g_srcImage.rows / 4), 0, 0, INTER_LINEAR);
//更新效果圖
imshow(WINDOW_NAME, g_srcImage1);
//imwrite("s_pos71_run7_img190.jpg", g_srcImage);
}
實驗結果