C++和opencv实现图像分割(二)
生活随笔
收集整理的這篇文章主要介紹了
C++和opencv实现图像分割(二)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、目標圖片:
二、分割目的:
分割識別圖中的紙盒區域
三、實現思路及步驟:
1.使用雙邊變換進行濾波操作,保留并增強邊緣信息
2.使用canny算子檢測邊緣信息,使用開運算去除小噪點
?
使用多邊形逼近,畫出邊緣輪廓,對輪廓進行篩選操作
?
使用矩形直角、平行等特征構建向量模型篩選輪廓,使用直線連接矩形的四個角點位置,畫出矩形位置
注:識別效果一般;采用mask-rcnn機器學習方法重新進行紙箱模型分割,效果有著顯著提升,可以進我的個人主頁查看,博客連接網址:https://blog.csdn.net/weixin_38341864/article/details/88819668
四、完整代碼實例:
#include <opencv2\opencv.hpp> #include <iostream> #include <math.h> #include <string.h>using namespace std; using namespace cv;#define PI 3.1415int thresh = 280, N = 1; //輪廓提取參數調節 float EpsilonThd = 0.05; float MaxRegion = 200000, MinRegion = 8000; float SharpeThd = 2.5; float AngleMaxThd = 105; float AngleMinThd = 75; float AngleParaThd = 10; float EqualThd = 10; //兩點是否為同一點的距離閾值void findSquares(const Mat& image, vector<vector<Point>>& squares); double AngleCal(Point pt1, Point pt2, Point pt0); void RemoveInvalid(vector<vector<Point>> &corner); //移除無效輪廓 bool CompareCorner(vector<Point> corner1, vector<Point> corner2); //判斷角點是否為同一個點 void drawSquares(Mat& image, const vector<vector<Point> >& squares);float getDistance(Point2f a, Point2f b) {return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2)); }int main() {Mat image = imread("D:\\photoclub\\2\\5_1.jpg");if (!image.data){cout << "打開圖片有誤" << endl;return -1;}Mat image_gray;vector<vector<Point>> squares;cvtColor(image, image_gray, COLOR_BGR2GRAY);imshow("SorceImage", image_gray);findSquares(image_gray, squares);RemoveInvalid(squares);drawSquares(image, squares);imshow("Result", image);waitKey();return 0; }// helper function: // finds a cosine of angle between vectors // from pt0->pt1 and from pt0->pt2 double AngleCal(Point pt1, Point pt2, Point pt0) {double dx1 = pt1.x - pt0.x;double dy1 = pt1.y - pt0.y;double dx2 = pt2.x - pt0.x;double dy2 = pt2.y - pt0.y;return (dx1*dx2 + dy1 * dy2) / sqrt((dx1*dx1 + dy1 * dy1)*(dx2*dx2 + dy2 * dy2) + 1e-10); }void findSquares(const Mat& image, vector<vector<Point>>& squares) {/*找到長方形的函數image 輸入待查找長方形的圖片squares 輸出長方形點集*/int index = 0;RNG rng = theRNG();squares.clear();vector<vector<Point> > contours;for (int con = 0; con < 1; con++){Mat timg, cimg;image.convertTo(cimg, CV_8U, 0.5 + 0.5*con, 0);//cimg改變imshow("Image" + to_string(con), cimg);for (int th = 0; th < 3; th++){bilateralFilter(cimg, timg, -1, 3 + th * 3, 15);//雙邊Mat gray;for (int l = 0; l < N; l++){if (l == 0){Canny(timg, gray, 5, thresh, 5);//cannyimshow("canny" + to_string(th),gray);Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));dilate(gray, gray, kernel, Point(-1, -1));//膨脹}else{gray = timg >= (l + 1) * 255 / N;//***GRAY->timg}int kernel_length = timg.cols;//invalidfindContours(gray, contours, RETR_LIST, CHAIN_APPROX_NONE);//找輪廓Mat display;cvtColor(timg, display, COLOR_GRAY2BGR);vector<Point> approx;for (size_t i = 0; i < contours.size(); i++){approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*EpsilonThd, true); //多邊形擬合Scalar color = { (double)rng(256),(double)rng(256) ,(double)rng(256) };//隨機顏色drawContours(display, contours, i, color, 1);RotatedRect rect = minAreaRect(contours[i]); //矩形特征double sharpe = rect.size.width / rect.size.height; //矩形長比高if (approx.size() == 4 &&//容器大小fabs(contourArea(Mat(approx))) > MinRegion &&//面積范圍fabs(contourArea(Mat(approx))) < MaxRegion &&//面積范圍sharpe < SharpeThd && //長寬比范圍sharpe > 1.0 / SharpeThd &&//長寬比范圍isContourConvex(Mat(approx))){float maxAngle = 90, minAngle = 90;float rect_angle[3];for (int j = 2; j < 5; j++){float angle = acos(AngleCal(approx[j % 4], approx[j - 2], approx[j - 1])) * 180 / PI;rect_angle[j - 2] = angle;maxAngle = MAX(maxAngle, angle);minAngle = MIN(minAngle, angle);}float paral = (abs(180 - rect_angle[1] - rect_angle[0]) + abs(180 - rect_angle[1] - rect_angle[2])) / 2;if (maxAngle < AngleMaxThd && minAngle > AngleMinThd && paral < AngleParaThd)squares.push_back(approx);}}imshow("輪廓"+to_string(index), display);index++;}}}}void RemoveInvalid(vector<vector<Point>> &corner) {if (corner.size() == 0)return;for (int i = 1; i < corner.size(); i++){vector<Point> temp = corner[i];for (int j = 0; j < i; j++){vector<Point> temp2 = corner[j];if (CompareCorner(temp, temp2)){corner.erase(corner.begin() + i);i--;break;}}} }bool CompareCorner(vector<Point> corner1, vector<Point> corner2) {bool is_equal = false;for (int i = 0; i < corner1.size(); i++){Point temp = corner1[i];for (int j = 0; j < corner2.size(); j++){Point temp2 = corner2[j];if (getDistance((Point2f)temp, (Point2f)temp2) < EqualThd){is_equal = true;break;}}if (!is_equal)break;}return is_equal; }void drawSquares(Mat& image, const vector<vector<Point> >& squares) {/*在已經找到長方形的圖片上畫出長方形image 待圈出長方形的圖片squares 找到的長方形點集*/for (size_t i = 0; i < squares.size(); i++){const Point* p = &squares[i][0];int n = (int)squares[i].size();if (p->x > 3 && p->y > 3)polylines(image, &p, &n, 1, true, Scalar(0, 255, 0), 2, LINE_AA);} }?
總結
以上是生活随笔為你收集整理的C++和opencv实现图像分割(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pb 日期相关函数
- 下一篇: 百度 C++ 工程师的那些极限优化(内存