opencv——图像中关于轮廓的一些操作
生活随笔
收集整理的這篇文章主要介紹了
opencv——图像中关于轮廓的一些操作
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
背景:
vs2015+opencv3.4.14
圖像中斑點的輪廓提取、輪廓信息自定義保存和對于提取出的輪廓的連接操作。
上面是輪廓提取的關鍵函數(shù)以及最小外接矩形的和其四個頂點的表示。
其中P四個點的位置是后面要著重注意的,弄不清楚后面的操作也就亂了,注意**的圖。
1、定義結構體保存輪廓點信息
//定義結構圖:輪廓信息struct P_Rect{//提取特征://最小外接矩形的質(zhì)心、長寬、旋轉角度//輪廓面積int px;int py;float pwidth;float pheight;float pangle;float parea;};//定義結構圖:輪廓外部信息struct P_Rectout{//在一定范圍內(nèi)點的位置,各個距離int ox;int oy;float odistance;float oarea;};//矩形相鄰的兩個邊的長度float length1= abs(sqrtf(powf((P[0].x - P[1].x), 2) + powf((P[0].y - P[1].y), 2)));float length2 = abs(sqrtf(powf((P[1].x - P[2].x), 2) + powf((P[1].y - P[2].y), 2)));//正確找到長邊和短邊if (length1 >= length2){p_rect.pwidth = length1;p_rect.pheight = length2;p_rect.pangle = cvFastArctan(abs(P[1].y - P[0].y), abs(P[1].x - P[0].x));//指向長的方向的角度,不是矩形原來的角度,矩形原來的角度解析可去 查找findContours函數(shù)}else{p_rect.pwidth = length2;p_rect.pheight = length1;if (P[2].x == P[1].x)//使用arctan的注意事項{p_rect.pangle = 90;}else{p_rect.pangle = -abs(cvFastArctan(abs(P[2].y - P[1].y), abs(P[2].x - P[1].x)));}} //中心x和yp_rect.px=rect.center.x;p_rect.py = rect.center.y; //面積,是真實面積不是最小外接矩形面積p_rect.parea = contourArea(contours[i]); //保存到容器中P_rect.push_back(p_rect);//小于半徑范圍內(nèi)點的集合vector<P_Rectout> p_rectOut;float r = 20;for (int j = 0; j < contours.size(); j++){RotatedRect orect = minAreaRect(contours[j]);float distance = abs(sqrtf(powf((rect.center.x - orect.center.x), 2) + powf((rect.center.x - orect.center.y), 2)));if (distance < r){P_Rectout p_rectout;p_rectout.ox = orect.center.x;p_rectout.oy = orect.center.y;p_rectout.odistance = distance;p_rectout.oarea= contourArea(contours[j]);p_rectOut.push_back(p_rectout);//line(imageContours, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[j].px, P_rect[j].py), Scalar(255), 3);}}P_rectout.push_back(p_rectOut);}2、以每個點一定半徑范圍為依據(jù)連線
//一定范圍內(nèi)最近點連線//以第一個點sta為起點,尋找一定半徑(r)范圍內(nèi)的所有臨近點mid[],連線,直到半徑(r)內(nèi)無此特征的點為止,遍歷所有點float r = 500;for (int i = 0; i < P_rect.size(); i++){for (int j = 0; j < P_rect.size(); j++){float distance = abs(sqrtf(powf((P_rect[i].px - P_rect[j].px), 2) + powf((P_rect[i].py - P_rect[j].py), 2)));if (distance > 0 && distance < r){line(imageContours, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[j].px, P_rect[j].py), Scalar(255), 2);}}}3、最短距離連線
//最短距離連線vector<Point> yet_link;//保存以完成連線點for (int i = 0; i < (P_rect.size()-1); i++){float distance_min = 10000000000;//順便定個大數(shù)int p_near = 0;for (int j = 0; j < P_rect.size(); j++){bool flag = 1;for (int k = 0; k < yet_link.size(); k++)//保證每個點不返回頭和連過的點再次連一遍,看情況取舍{if (i == yet_link[k].y && j == yet_link[k].x){flag = 0;continue;}}if (flag){float distance = abs(sqrtf(powf((P_rect[i].px - P_rect[j].px), 2) + powf((P_rect[i].py - P_rect[j].py), 2)));if (distance > 0 && distance<distance_min){p_near = j;distance_min = distance;}}}yet_link.push_back(Point(i, p_near));line(imageContours2, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[p_near].px, P_rect[p_near].py), Scalar(255), 2);}完整代碼如下;
#include <iostream> #include <opencv2\opencv.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp>using namespace std; using namespace cv;//定義結構圖:輪廓信息 struct P_Rect {//提取特征://最小外接矩形的質(zhì)心、長寬、旋轉角度//輪廓面積int px;int py;float pwidth;float pheight;float pangle;float parea; };//定義結構圖:輪廓外部信息 struct P_Rectout {//在一定范圍內(nèi)點的位置,各個距離int ox;int oy;float odistance;float oarea; };int main() {//讀入圖像Mat img_original = imread("北斗七星.bmp");//imwrite("1.bmp", img_original);Mat img_original_gray;cvtColor(img_original, img_original_gray, CV_BGR2GRAY);//轉為灰度圖Mat img_original_bin;threshold(img_original_gray, img_original_bin, 100, 255, CV_THRESH_BINARY);//二值化//尋找輪廓vector<vector<Point>> contours;vector<Vec4i> hierarchy;//存儲查找到的第i個輪廓的后[i][0]、前[i][1]、父[i][2]、子輪廓[i][3]findContours(img_original_bin, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE, Point());Mat imageContours = Mat::zeros(img_original_bin.size(), CV_8UC1); //畫布1Mat imageContours2 = Mat::zeros(img_original_bin.size(), CV_8UC1); //畫布2//for (int i = 0; i < contours.size(); i++)//{// //繪制輪廓的最小外接正矩形// Rect boundRect = boundingRect(Mat(contours[i]));// rectangle(imageContours, Point(boundRect.x, boundRect.y), Point(boundRect.x + boundRect.width, boundRect.y + boundRect.height), Scalar(255), 2, 8);//}vector<P_Rect> P_rect;vector<vector<P_Rectout> > P_rectout;for (int i = 0; i < contours.size(); i++){float area= contourArea(contours[i]);if (area < 10)continue;//******P_Rect p_rect;drawContours(imageContours, contours, i, Scalar(255), -1, 8, hierarchy);drawContours(imageContours2, contours, i, Scalar(255), -1, 8, hierarchy);//繪制每個輪廓的最小外接矩形RotatedRect rect= minAreaRect(contours[i]);Point2f P[4];//初始化矩形四個頂點坐標rect.points(P);for (int i = 0; i < 4; i++){//line(imageContours, P[i], P[(i + 1) % 4], Scalar(255), 2);}float length1= abs(sqrtf(powf((P[0].x - P[1].x), 2) + powf((P[0].y - P[1].y), 2)));float length2 = abs(sqrtf(powf((P[1].x - P[2].x), 2) + powf((P[1].y - P[2].y), 2)));if (length1 >= length2){p_rect.pwidth = length1;p_rect.pheight = length2;p_rect.pangle = cvFastArctan(abs(P[1].y - P[0].y), abs(P[1].x - P[0].x));}else{p_rect.pwidth = length2;p_rect.pheight = length1;if (P[2].x == P[1].x){p_rect.pangle = 90;}else{p_rect.pangle = -abs(cvFastArctan(abs(P[2].y - P[1].y), abs(P[2].x - P[1].x)));}}p_rect.px=rect.center.x;p_rect.py = rect.center.y;p_rect.parea = contourArea(contours[i]);P_rect.push_back(p_rect);//********vector<P_Rectout> p_rectOut;float r = 20;for (int j = 0; j < contours.size(); j++){RotatedRect orect = minAreaRect(contours[j]);float distance = abs(sqrtf(powf((rect.center.x - orect.center.x), 2) + powf((rect.center.x - orect.center.y), 2)));if (distance < r){P_Rectout p_rectout;p_rectout.ox = orect.center.x;p_rectout.oy = orect.center.y;p_rectout.odistance = distance;p_rectout.oarea= contourArea(contours[j]);p_rectOut.push_back(p_rectout);//line(imageContours, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[j].px, P_rect[j].py), Scalar(255), 3);}}P_rectout.push_back(p_rectOut);}//一定范圍內(nèi)最近點連線//以第一個點sta為起點,尋找一定半徑(r)范圍內(nèi)的所有臨近點mid[],連線,直到半徑(r)內(nèi)無此特征的點為止,遍歷所有點float r = 500;/*Point2f sta = center_each[0];vector<Point2f> mid;*/for (int i = 0; i < P_rect.size(); i++){for (int j = 0; j < P_rect.size(); j++){float distance = abs(sqrtf(powf((P_rect[i].px - P_rect[j].px), 2) + powf((P_rect[i].py - P_rect[j].py), 2)));if (distance > 0 && distance < r){//mid.push_back(center_each[j]);line(imageContours, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[j].px, P_rect[j].py), Scalar(255), 2);}}}//最短距離連線vector<Point> yet_link;for (int i = 0; i < (P_rect.size()-1); i++){float distance_min = 10000000000;int p_near = 0;for (int j = 0; j < P_rect.size(); j++){bool flag = 1;for (int k = 0; k < yet_link.size(); k++){if (i == yet_link[k].y && j == yet_link[k].x){flag = 0;continue;}}if (flag){float distance = abs(sqrtf(powf((P_rect[i].px - P_rect[j].px), 2) + powf((P_rect[i].py - P_rect[j].py), 2)));if (distance > 0 && distance<distance_min){p_near = j;distance_min = distance;}}}yet_link.push_back(Point(i, p_near));line(imageContours2, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[p_near].px, P_rect[p_near].py), Scalar(255), 2);}}總結
以上是生活随笔為你收集整理的opencv——图像中关于轮廓的一些操作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智联招聘自动刷新简历软件
- 下一篇: 场景背后见真章:银行数字化转型持续深入