#include "opencv2/highgui/highgui.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> // Mser車牌目標檢測 std::vector<cv::Rect> mserGetPlate(cv::Mat srcImage) { // HSV空間轉換 cv::Mat gray, gray_neg; cv::Mat hsi; cv::cvtColor(srcImage, hsi, CV_BGR2HSV); // 通道分離 std::vector<cv::Mat> channels; cv::split(hsi, channels); // 提取h通道 gray = channels[1]; // 灰度轉換 cv::cvtColor(srcImage, gray, CV_BGR2GRAY); // 取反值灰度 gray_neg = 255 - gray; std::vector<std::vector<cv::Point> > regContours; std::vector<std::vector<cv::Point> > charContours; // MSER+操做 cv::MSER(2, 10, 5000, 0.5, 0.3)(gray, regContours); // MSER-操做 cv::MSER(2, 2, 400, 0.1, 0.3)(gray_neg, charContours); cv::Mat mserMapMat = cv::Mat::zeros(srcImage.size(), CV_8UC1); cv::Mat mserNegMapMat = cv::Mat::zeros(srcImage.size(), CV_8UC1); // MSER+ 檢測 for(int i = (int)regContours.size()-1; i >= 0; i--) { // 根據檢測區域點生成mser+結果 const std::vector<cv::Point>& r = regContours[i]; for (int j = 0; j < (int)r.size(); j++ ) { cv::Point pt = r[j]; mserMapMat.at<unsigned char>(pt) = 255; } } // MSER- 檢測 for(int i = (int)charContours.size()-1; i >= 0; i--) { // 根據檢測區域點生成mser-結果 const std::vector<cv::Point>& r = charContours[i]; for (int j = 0; j < (int)r.size(); j++ ) { cv::Point pt = r[j]; mserNegMapMat.at<unsigned char>(pt) = 255; } } // mser結果輸出 cv::Mat mserResMat; // mser+與mser-位與操做 mserResMat= mserMapMat & mserNegMapMat; cv::imshow("mserMapMat", mserMapMat); cv::imshow("mserNegMapMat", mserNegMapMat); cv::imshow("mserResMat", mserResMat); // 閉操做鏈接縫隙 cv::Mat mserClosedMat; cv::morphologyEx(mserResMat, mserClosedMat, cv::MORPH_CLOSE, cv::Mat::ones(1, 20, CV_8UC1)); cv::imshow("mserClosedMat", mserClosedMat); // 尋找外部輪廓 std::vector<std::vector<cv::Point> > plate_contours; cv::findContours(mserClosedMat, plate_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0)); // 候選車牌區域判斷輸出 std::vector<cv::Rect> candidates; for (size_t i = 0; i != plate_contours.size(); ++i) { // 求解最小外界矩形 cv::Rect rect = cv::boundingRect(plate_contours[i]); // 寬高比例 double wh_ratio = rect.width / double(rect.height); // 不符合尺寸條件判斷 if (rect.height > 20 && wh_ratio > 4 && wh_ratio < 7) candidates.push_back(rect); } return candidates; } int main() { cv::Mat srcImage = cv::imread("car.jpg"); if(srcImage .empty()) return-1; // 候選車牌區域檢測 std::vector<cv::Rect> candidates; candidates = mserGetPlate(srcImage); // 車牌區域顯示 for (int i = 0; i < candidates.size(); ++i) { cv::imshow("rect", srcImage(candidates[i])); cv::waitKey(); } return 0; }
原圖ios
效果圖ui