opencv 擷取輪廓中的影象——實現PS中的摳圖功能 Opencv extract area circled by contour
阿新 • • 發佈:2019-01-04
opencv 擷取輪廓中的影象——實現PS中利用蒙版摳圖的功能(Using Opencv extract area circled by contour)
順手秀了一把英語~~
我時常感慨,要是PhotoShop要是開源的多好啊,這得造福多少從事計算機視覺的碼農們啊~ 既然不開源,那就自己摸索吧,我希望從這篇博文開始我能一步步把PS中的功能給分解出來,歡迎指正交流
我們很容易用findContours()函式將影象中的輪廓提取出來,但是並沒有將輪廓所包圍的影象輸出的函式,以下是幾個有類似功能的函式:
cvimageroi():得到包圍ROI(感興趣區域)的矩形區域,可以直接把輪廓點集作為引數給進去然後返回包圍這個輪廓的最佳矩形點集,然後再用 Mat的成員函式Mat(Rec)把這個區域提取出來。遺憾的是這樣只能提取矩形區域,無法提取不規則區域。
boundingRect():這個同上一個是一樣的功能,也是得到矩形區域。
進入正題
首先將原影象灰度化,二值化,然後提取輪廓,進行排除、去噪處理之後用drawContours()函式把輪廓填充為白色。具體做法是:
Mat hole(res.size(), CV_8U, Scalar(0)); //新建一個黑色的遮罩圖層
cv::drawContours(hole, contours1, -1, Scalar(255), CV_FILLED); //在遮罩圖層上,將輪廓裡面的空間用白色畫素填充
之後將原圖用copyTo()函式疊加到遮罩圖層上,就大功告成了。
#include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include <iostream> using namespace cv; using namespace std; void main() { Mat original = imread("D:\\res.png"); namedWindow("My original"); imshow("My original", original); Mat gray = original; cv::cvtColor(gray, gray, CV_RGB2GRAY);//灰度化 int thresh_size = (100 / 4) * 2 + 1; //自適應二值化閾值 adaptiveThreshold(gray, gray, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, thresh_size, thresh_size / 3); morphologyEx(gray, gray, MORPH_OPEN, Mat());//形態學開運算去噪點 vector<vector<Point> > contours; cv::findContours(gray, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); //找輪廓 vector<vector<Point>> contours1; for (int i = 0; i < contours.size(); ++i) { if (contours[i].size() > 200)//將比較小的輪廓剔除掉 { contours1.push_back(contours[i]); } } /*可以加入以下功能*/ //vector<vector<Point>> contours2; //vector<Point> approx_poly;//存放頂點 //for (int i = 0; i < contours1.size(); ++i) //{ //double eps = contours1[i].size()*0.08;//精度 //approxPolyDP(contours1[i], approx_poly, eps, true);//用另一條頂點較少的曲線來逼近一條曲線或者一個多邊形 //if ((approx_poly.size() != 4) || (!isContourConvex(approx_poly)))//提取只有4個頂點的輪廓和凸多邊形 //{ // continue; //} //else { //contours2.push_back(contours1[i]); //} //} Mat hole(gray.size(), CV_8U, Scalar(0)); //遮罩圖層 cv::drawContours(hole, contours1, -1, Scalar(255), CV_FILLED); //在遮罩圖層上,用白色畫素填充輪廓 namedWindow("My hole"); imshow("My hole", hole); Mat crop(original.rows, original.cols, CV_8UC3); original.copyTo(crop, hole);//將原影象拷貝進遮罩圖層 namedWindow("My warpPerspective"); imshow("My warpPerspective", crop); waitKey(0); }