日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

EasyPR如何添加绿牌C++版

發(fā)布時(shí)間:2023/12/20 c/c++ 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 EasyPR如何添加绿牌C++版 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ? ? 終于答辯結(jié)束了,這個(gè)項(xiàng)目忘的也差不多了,今天正巧沒事準(zhǔn)備整理一下,本人菜雞一枚,本科畢業(yè)設(shè)計(jì)題目是《基于OpenCV的車牌識(shí)別系統(tǒng)》,這個(gè)項(xiàng)目差不多研究了半個(gè)月才看懂,當(dāng)時(shí)我給導(dǎo)師看這個(gè)項(xiàng)目的時(shí)候,導(dǎo)師直接說這些東西都是別人的,你什么都不做,這工作量有點(diǎn)少,怕我答辯時(shí)候過不了,之后就是讓我加功能,(你這個(gè)可以檢測(cè)綠牌嗎?還有你這個(gè)識(shí)別算法,用的是什么,能不能用其他的,建議加個(gè)綠牌,并且做個(gè)其他識(shí)別算法和你這個(gè)對(duì)比一下,工作量看起來多一些),還是太懶了我只加了綠牌,之后又被導(dǎo)師數(shù)落了一頓。
? ? ? ? 這個(gè)項(xiàng)目寫的聽清楚的,還有開發(fā)者文檔參考,作者也把各個(gè)版本的配置方式貼出來了。我自己只是用MFC畫了一個(gè)界面,里面就是調(diào)作者寫好的函數(shù),我自己加了綠牌,修改了部分代碼。

1.添加綠色

? ? ? ? 在枚舉顏色里面添加GREEN。在config.h文件中:

enum Color { BLUE, YELLOW, WHITE, GREEN,UNKNOWN };

2.添加綠色HSV

? ? ? ?這里我設(shè)置的是35-80,在core_func.cpp文件中colorMatch函數(shù)中添加。修改后的代碼如下:

Mat colorMatch(const Mat &src, Mat &match, const Color r,const bool adaptive_minsv) {// if use adaptive_minsv// min value of s and v is adaptive to hconst float max_sv = 255;const float minref_sv = 64;const float minabs_sv = 95; //95;// H range of blue const int min_blue = 100; // 100const int max_blue = 140; // 140// H range of yellowconst int min_yellow = 15; // 15const int max_yellow = 40; // 40// H range of whiteconst int min_white = 0; // 15const int max_white = 30; // 40//Louis add,green // H range of greenconst int min_green = 35; // 35const int max_green = 80; // 80Mat src_hsv;// convert to HSV spacecvtColor(src, src_hsv, CV_BGR2HSV);std::vector<cv::Mat> hsvSplit;split(src_hsv, hsvSplit);equalizeHist(hsvSplit[2], hsvSplit[2]);merge(hsvSplit, src_hsv);// match to find the colorint min_h = 0;int max_h = 0;switch (r) {case BLUE:min_h = min_blue;max_h = max_blue;break;case YELLOW:min_h = min_yellow;max_h = max_yellow;break;case WHITE:min_h = min_white;max_h = max_white;break;//Louis add,green case GREEN:min_h = min_green;max_h = max_green;break;default:// Color::UNKNOWNbreak;}float diff_h = float((max_h - min_h) / 2);float avg_h = min_h + diff_h;int channels = src_hsv.channels();int nRows = src_hsv.rows;// consider multi channel imageint nCols = src_hsv.cols * channels;if (src_hsv.isContinuous()) {nCols *= nRows;nRows = 1;}int i, j;uchar* p;float s_all = 0;float v_all = 0;float count = 0;for (i = 0; i < nRows; ++i) {p = src_hsv.ptr<uchar>(i);for (j = 0; j < nCols; j += 3) {int H = int(p[j]); // 0-180int S = int(p[j + 1]); // 0-255int V = int(p[j + 2]); // 0-255s_all += S;v_all += V;count++;bool colorMatched = false;if (H > min_h && H < max_h) {float Hdiff = 0;if (H > avg_h)Hdiff = H - avg_h;elseHdiff = avg_h - H;float Hdiff_p = float(Hdiff) / diff_h;float min_sv = 0;if (true == adaptive_minsv)min_sv =minref_sv -minref_sv / 2 *(1- Hdiff_p); // inref_sv - minref_sv / 2 * (1 - Hdiff_p)elsemin_sv = minabs_sv; // addif ((S > min_sv && S < max_sv) && (V > min_sv && V < max_sv))colorMatched = true;}if (colorMatched == true) {p[j] = 0;p[j + 1] = 0;p[j + 2] = 255;}else {p[j] = 0;p[j + 1] = 0;p[j + 2] = 0;}}}// cout << "avg_s:" << s_all / count << endl;// cout << "avg_v:" << v_all / count << endl;// get the final binaryMat src_grey;std::vector<cv::Mat> hsvSplit_done;split(src_hsv, hsvSplit_done);src_grey = hsvSplit_done[2];match = src_grey;return src_grey;}

3.getPlateType中添加綠色

這部分也在core_func.cpp文件中。

Color getPlateType(const Mat &src, const bool adaptive_minsv) {float max_percent = 0;Color max_color = UNKNOWN;float blue_percent = 0;float yellow_percent = 0;float white_percent = 0;float green_percent = 0;if (plateColorJudge(src, BLUE, adaptive_minsv, blue_percent) == true) {// cout << "BLUE" << endl;return BLUE;} else if (plateColorJudge(src, YELLOW, adaptive_minsv, yellow_percent) ==true) {// cout << "YELLOW" << endl;return YELLOW;} else if (plateColorJudge(src, WHITE, adaptive_minsv, white_percent) ==true) {// cout << "WHITE" << endl;return WHITE;}else if (plateColorJudge(src, GREEN, adaptive_minsv, green_percent) ==true) {// cout << "GREEN" << endl;return GREEN;}else {//std::cout << "OTHER" << std::endl;/*max_percent = blue_percent > yellow_percent ? blue_percent : yellow_percent;max_color = blue_percent > yellow_percent ? BLUE : YELLOW;max_color = max_percent > white_percent ? max_color : WHITE;*/// always return greenreturn GREEN;}}

4.顏色定位中添加綠色

plate_locate.cpp中plateColorLocate函數(shù),修改后如下:

int CPlateLocate::plateColorLocate(Mat src, vector<CPlate> &candPlates,int index) {vector<RotatedRect> rects_color_blue;rects_color_blue.reserve(64);vector<RotatedRect> rects_color_yellow;rects_color_yellow.reserve(64);vector<RotatedRect> rects_color_green;rects_color_green.reserve(64);vector<CPlate> plates_blue;plates_blue.reserve(64);vector<CPlate> plates_yellow;plates_yellow.reserve(64);vector<CPlate> plates_green;plates_green.reserve(64);Mat src_clone = src.clone();Mat src_b_blue;Mat src_b_yellow;Mat src_b_green; #pragma omp parallel sections{ #pragma omp section{colorSearch(src, BLUE, src_b_blue, rects_color_blue);deskew(src, src_b_blue, rects_color_blue, plates_blue, true, BLUE);//imshow("blue", src_b_blue);} #pragma omp section{colorSearch(src_clone, YELLOW, src_b_yellow, rects_color_yellow);deskew(src_clone, src_b_yellow, rects_color_yellow, plates_yellow, true, YELLOW);} #pragma omp section{colorSearch(src_clone, GREEN, src_b_green, rects_color_green);deskew(src_clone, src_b_green, rects_color_green, plates_green, true, GREEN);//imshow("green", src_b_green);}}candPlates.insert(candPlates.end(), plates_blue.begin(), plates_blue.end());candPlates.insert(candPlates.end(), plates_yellow.begin(), plates_yellow.end());candPlates.insert(candPlates.end(), plates_green.begin(), plates_green.end());return 0; }

以上處理完基本可以實(shí)現(xiàn)對(duì)綠牌的定位,如果需要更高的準(zhǔn)確率,可以自己重新訓(xùn)練一下,加上綠牌,因?yàn)榫G牌的大小,顏色特征等都和藍(lán)牌差距太大。

5.字符分割部分

這部分主要更改個(gè)分割字符數(shù)量和二值化參數(shù),因?yàn)榫G牌是8個(gè)字符,藍(lán)牌7個(gè)字符,并且綠牌是背景顏色淺,車牌號(hào)顏色深,藍(lán)牌是背景顏色深,車牌號(hào)顏色淺,所以藍(lán)牌進(jìn)行反二值化,綠牌則是正二值化。如下是core.func.cpp文件中。

void spatial_ostu(InputArray _src, int grid_x, int grid_y, Color type) {Mat src = _src.getMat();int width = src.cols / grid_x;int height = src.rows / grid_y;// iterate through gridfor (int i = 0; i < grid_y; i++) {for (int j = 0; j < grid_x; j++) {Mat src_cell = Mat(src, Range(i * height, (i + 1) * height), Range(j * width, (j + 1) * width));if (type == BLUE) {cv::threshold(src_cell, src_cell, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);} else if (type == YELLOW) {cv::threshold(src_cell, src_cell, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);} else if (type == WHITE) {cv::threshold(src_cell, src_cell, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);}else if (type == GREEN) {cv::threshold(src_cell, src_cell, 0, 255, THRESH_OTSU + CV_THRESH_BINARY_INV);}else {cv::threshold(src_cell, src_cell, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);}}}}

如下是字符分割函數(shù)修改后,在chars_segment.cpp中:

int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec, Color color) {if (!input.data) return 0x01;Color plateType = color;Mat input_grey;cvtColor(input, input_grey, CV_BGR2GRAY);//imshow("cvt", input_grey);if (0) {imshow("plate", input_grey);waitKey(0);destroyWindow("plate");}Mat img_threshold;img_threshold = input_grey.clone();spatial_ostu(img_threshold, 8, 2, plateType);//imshow("ostu", img_threshold);if (0) {imshow("plate", img_threshold);waitKey(0);destroyWindow("plate");}// remove liuding and hor lines // also judge weather is plate use jump countif (!clearLiuDing(img_threshold)) return 0x02;Mat img_contours;img_threshold.copyTo(img_contours);vector<vector<Point> > contours;findContours(img_contours,contours, // a vector of contoursCV_RETR_EXTERNAL, // retrieve the external contoursCV_CHAIN_APPROX_NONE); // all pixels of each contours// Mat dst = input;//for (vector<Point> point : contours) {// RotatedRect rotatedRect = minAreaRect(point);// rectangle(dst, rotatedRect.boundingRect(), Scalar(255,0,255));//}//imshow("dst", dst);vector<vector<Point> >::iterator itc = contours.begin();vector<Rect> vecRect;while (itc != contours.end()) {Rect mr = boundingRect(Mat(*itc));Mat auxRoi(img_threshold, mr);if (verifyCharSizes(auxRoi)) vecRect.push_back(mr);++itc;}if (vecRect.size() == 0) return 0x03;vector<Rect> sortedRect(vecRect);std::sort(sortedRect.begin(), sortedRect.end(),[](const Rect& r1, const Rect& r2) { return r1.x < r2.x; });size_t specIndex = 0;if(color == GREEN)specIndex = GetSpecificRectNew(sortedRect);//new carelsespecIndex = GetSpecificRect(sortedRect);//old carRect chineseRect;if (specIndex < sortedRect.size())chineseRect = GetChineseRect(sortedRect[specIndex]);elsereturn 0x04;if (0) {rectangle(img_threshold, chineseRect, Scalar(255));imshow("plate", img_threshold);waitKey(0);destroyWindow("plate");}vector<Rect> newSortedRect;newSortedRect.push_back(chineseRect);if (color == GREEN)RebuildRectNew(sortedRect, newSortedRect, specIndex);elseRebuildRect(sortedRect, newSortedRect, specIndex);if (newSortedRect.size() == 0) return 0x05;Mat dst = input;bool useSlideWindow = true;bool useAdapThreshold = true;//bool useAdapThreshold = CParams::instance()->getParam1b();for (size_t i = 0; i < newSortedRect.size(); i++) {Rect mr = newSortedRect[i];//rectangle(dst, mr, Scalar(255, 0, 255));// Mat auxRoi(img_threshold, mr);Mat auxRoi(input_grey, mr);Mat newRoi;if (i == 0) {if (useSlideWindow) {float slideLengthRatio = 0.1f;//float slideLengthRatio = CParams::instance()->getParam1f();if (!slideChineseWindow(input_grey, mr, newRoi, plateType, slideLengthRatio, useAdapThreshold))judgeChinese(auxRoi, newRoi, plateType);}elsejudgeChinese(auxRoi, newRoi, plateType);}else {if (BLUE == plateType) {threshold(auxRoi, newRoi, 0, 255, CV_THRESH_BINARY + CV_THRESH_OTSU);}else if (YELLOW == plateType) {threshold(auxRoi, newRoi, 0, 255, CV_THRESH_BINARY_INV + CV_THRESH_OTSU);}else if (WHITE == plateType) {threshold(auxRoi, newRoi, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);}else if (GREEN == plateType) {threshold(auxRoi, newRoi, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);}else {threshold(auxRoi, newRoi, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);}newRoi = preprocessChar(newRoi);}if (0) {if (i == 0) {imshow("input_grey", input_grey);waitKey(0);destroyWindow("input_grey");}if (i == 0) {imshow("newRoi", newRoi);waitKey(0);destroyWindow("newRoi");}}resultVec.push_back(newRoi);}//imshow("dst", dst);return 0; }

添加如下兩個(gè)函數(shù),因?yàn)樽址麛?shù)不同,切割函數(shù)也不相同。

int CCharsSegment::GetSpecificRectNew(const vector<Rect>& vecRect) {vector<int> xpositions;int maxHeight = 0;int maxWidth = 0;for (size_t i = 0; i < vecRect.size(); i++) {xpositions.push_back(vecRect[i].x);if (vecRect[i].height > maxHeight) {maxHeight = vecRect[i].height;}if (vecRect[i].width > maxWidth) {maxWidth = vecRect[i].width;}}int specIndex = 0;for (size_t i = 0; i < vecRect.size(); i++) {Rect mr = vecRect[i];int midx = mr.x + mr.width / 2;// use prior knowledage to find the specific character// position in 1/8 and 2/8if ((mr.width > maxWidth * 0.6 || mr.height > maxHeight * 0.6) &&(midx < int(m_theMatWidth / 8.15f) * kSymbolIndex &&midx > int(m_theMatWidth / 8.15f) * (kSymbolIndex - 1))) {specIndex = i;}}return specIndex; }int CCharsSegment::RebuildRectNew(const vector<Rect>& vecRect,vector<Rect>& outRect, int specIndex) {int count = 7;//Louis changed 6->7, for green plate carfor (size_t i = specIndex; i < vecRect.size() && count; ++i, --count) {outRect.push_back(vecRect[i]);}return 0; } }

以上改完基本可以實(shí)現(xiàn)對(duì)綠牌的識(shí)別,我只改了我用到的部分函數(shù),其他未修改的同理。好久沒看這個(gè)項(xiàng)目了,應(yīng)該改的就這么多了,還有就是我訓(xùn)練的時(shí)候只用了10幾張綠牌,關(guān)鍵是沒數(shù)據(jù)集。。。

總結(jié)

以上是生活随笔為你收集整理的EasyPR如何添加绿牌C++版的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。