Opencv檢測交通中紅色標識輪廓c++程式碼例項及執行結果
阿新 • • 發佈:2019-01-04
環境vs2013+opencv2.4.9
c++程式碼
#include<opencv2/opencv.hpp> #include<iostream> #define PI 3.1415926 using namespace std; using namespace cv; void RGB2HSV(double red, double green, double blue, double& hue, double& saturation, double& intensity) { double r, g, b; double h, s, i; double sum; double minRGB, maxRGB; double theta; r = red / 255.0; g = green / 255.0; b = blue / 255.0; minRGB = ((r<g) ? (r) : (g)); minRGB = (minRGB<b) ? (minRGB) : (b); maxRGB = ((r>g) ? (r) : (g)); maxRGB = (maxRGB>b) ? (maxRGB) : (b); sum = r + g + b; i = sum / 3.0; if (i<0.001 || maxRGB - minRGB<0.001) { h = 0.0; s = 0.0; } else { s = 1.0 - 3.0*minRGB / sum; theta = sqrt((r - g)*(r - g) + (r - b)*(g - b)); theta = acos((r - g + r - b)*0.5 / theta); if (b <= g) h = theta; else h = 2 * PI - theta; if (s <= 0.01) h = 0; } hue = (int)(h * 180 / PI); saturation = (int)(s * 100); intensity = (int)(i * 100); } void fillHole(const Mat srcBw, Mat &dstBw) { Size m_Size = srcBw.size(); Mat Temp = Mat::zeros(m_Size.height + 2, m_Size.width + 2, srcBw.type());//延展影象 srcBw.copyTo(Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1))); cv::floodFill(Temp, Point(0, 0), Scalar(255));//填充區域 Mat cutImg;//裁剪延展的影象 Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)).copyTo(cutImg); dstBw = srcBw | (~cutImg); } int main() { Mat srcImg; srcImg = imread("1.jpg");//讀取檔案 resize(srcImg,srcImg,Size(200,200));//重定義圖片大小 imshow("srcImg", srcImg); int width = srcImg.cols; int height = srcImg.rows; /* vector<Mat> hsv_vec; Mat H, S, V; cvtColor(srcImg, hsvImg, CV_BGR2HSV); split(hsvImg, hsv_vec); H = hsv_vec[0]; S = hsv_vec[1]; V = hsv_vec[2]; H.convertTo(H, CV_32F); S.convertTo(S, CV_32F); V.convertTo(V, CV_32F); if ((H >= 337 && H <= 360 || H >= 0 && H <= 10)) */ int x, y; double B = 0.0, G = 0.0, R = 0.0, H = 0.0, S = 0.0, V = 0.0; Mat vec_rgb = Mat::zeros(srcImg.size(), CV_8UC1); for (x = 0; x < height; x++) { for (y = 0; y < width; y++) { B = srcImg.at<Vec3b>(x, y)[0]; G = srcImg.at<Vec3b>(x, y)[1]; R = srcImg.at<Vec3b>(x, y)[2]; RGB2HSV(R, G, B, H, S, V); //紅色範圍,範圍參考的網上。可以自己調 if ((H >= 312 && H <= 360 || H >= 0 && H <= 20) && (S >= 17 && S <= 100) && (V>18 && V < 100)) vec_rgb.at<uchar>(x, y) = 255; } } imshow("hsv", vec_rgb); medianBlur(vec_rgb, vec_rgb, 3);//中值濾波 imshow("medianBlur", vec_rgb); Mat element = getStructuringElement(MORPH_ELLIPSE,Size(2*1+1,2*1+1),Point(1,1)); Mat element1 = getStructuringElement(MORPH_ELLIPSE, Size(2 * 3 + 1, 2 * 3 + 1), Point(3, 3)); erode(vec_rgb, vec_rgb, element);//腐蝕 imshow("erode", vec_rgb); dilate(vec_rgb, vec_rgb, element1);//膨脹 imshow("dilate", vec_rgb); fillHole(vec_rgb, vec_rgb);//填充 imshow("fillHole", vec_rgb); //cvtColor(srcImg, grayImg, CV_BGR2GRAY); vector<vector<Point>>contours; //輪廓 vector<Vec4i> hierarchy;//分層 findContours(vec_rgb, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//尋找輪廓 vector<vector<Point>> contours_poly(contours.size()); //近似後的輪廓點集 vector<Rect> boundRect(contours.size()); //包圍點集的最小矩形vector vector<Point2f> center(contours.size()); //包圍點集的最小圓形vector vector<float> radius(contours.size()); //包圍點集的最小圓形半徑vector for (int i = 0; i < contours.size(); i++) { approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); //對多邊形曲線做適當近似,contours_poly[i]是輸出的近似點集 boundRect[i] = boundingRect(Mat(contours_poly[i])); //計算並返回包圍輪廓點集的最小矩形 minEnclosingCircle(contours_poly[i], center[i], radius[i]);//計算並返回包圍輪廓點集的最小圓形及其半徑 } Mat drawing = Mat::zeros(vec_rgb.size(), CV_8UC3); for (int i = 0; i< contours.size(); i++) { Scalar color = (0, 0, 255);//藍色線畫輪廓 drawContours(drawing, contours_poly, i, color, 1, 8, hierarchy, 0, Point());//根據輪廓點集contours_poly和輪廓結構hierarchy畫出輪廓 rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);//畫矩形,tl矩形左上角,br右上角 circle(drawing, center[i], (int)radius[i], color, 2, 8, 0); //畫圓形 } /// 顯示在一個視窗 namedWindow("Contours", CV_WINDOW_AUTOSIZE); imshow("Contours", drawing); //system("pause"); waitKey(); return 0; }
執行結果