亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

利用OpenCV怎么對車牌的字符進行分割

發布時間:2020-11-30 15:52:10 來源:億速云 閱讀:301 作者:Leah 欄目:開發技術

這篇文章給大家介紹利用OpenCV怎么對車牌的字符進行分割,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。


檢測輪廓進行分割

邊緣檢測

對圖像進行邊緣檢測,這里采用的是 Canny 邊緣檢測,處理后的結果如下:

利用OpenCV怎么對車牌的字符進行分割

可以看到每個字的邊緣都被描繪出來了,接下來就將每個字的輪廓獲取出來。

檢測輪廓

直接使用 findContours() 將所有輪廓提取出來,再將其在原圖中畫出來看看效果:

利用OpenCV怎么對車牌的字符進行分割

可以看到不僅僅是每個字被框出來了,還有內部以及圖像中表現特殊部分的輪廓也有,接下來我們就根據每個字的大致大小篩選出我們想要的結果:

利用OpenCV怎么對車牌的字符進行分割

這樣看起來是不是就成功了,然后根據輪廓位置將每個字提取出來就行了,不過在這里每個輪廓的前后順序不一定是圖像中的位置,這里我使用每個輪廓左上角橫坐標 x 的大小來排序。

完整代碼:

#include <iostream> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
#include <map>

using namespace std;
using namespace cv;

int main() {
 Mat img = imread("number.jpg");
 Mat gray_img;
 // 生成灰度圖像
 cvtColor(img, gray_img, CV_BGR2GRAY);
 // 高斯模糊
 Mat img_gau;
 GaussianBlur(gray_img, img_gau, Size(3, 3), 0, 0);
 // 閾值分割
 Mat img_seg;
 threshold(img_gau, img_seg, 0, 255, THRESH_BINARY + THRESH_OTSU);
 // 邊緣檢測,提取輪廓
 Mat img_canny;
 Canny(img_seg, img_canny, 200, 100);
 vector<vector<Point>> contours;
 vector<Vec4i> hierarchy;
 findContours(img_canny, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point());
 int size = (int)(contours.size());
 // 保存符號邊框的序號
 vector<int> num_order;
 map<int, int> num_map;
 for (int i = 0; i < size; i++) {
 // 獲取邊框數據
 Rect number_rect = boundingRect(contours[i]);
 int width = number_rect.width;
 int height = number_rect.height;
 // 去除較小的干擾邊框,篩選出合適的區域
 if (width > img.cols/10 && height > img.rows/2) {
 rectangle(img_seg, number_rect.tl(), number_rect.br(), Scalar(255, 255, 255), 1, 1, 0);
 num_order.push_back(number_rect.x);
 num_map[number_rect.x] = i;
 }
 }
 // 按符號順序提取
 sort(num_order.begin(), num_order.end());
 for (int i = 0; i < num_order.size(); i++) {
 Rect number_rect = boundingRect(contours[num_map.find(num_order[i])->second]);
 Rect choose_rect(number_rect.x, 0, number_rect.width, gray_img.rows);
 Mat number_img = gray_img(choose_rect);
 imshow("number" + to_string(i), number_img);
 // imwrite("number" + to_string(i) + ".jpg", number_img);
 }
 imshow("添加方框", gray_img);
 waitKey(0);
 return 0;
}

像素值判斷進行分割

分割方法:首先判斷每一列的像素值大于 0 的像素個數超過5個時,認為此列是有數字的,記錄每列像素是否大于 5,產生一個數組。

// 確認為 1 的像素
 int pixrow[1000];
 for (int i = 0; i < roi_col - 1; i++) {
 for (int j = 0; j < roi_row - 1; j++) {
 pix = img_threadhold.at<uchar>(j, i);
 pixrow[i] = 0;
 if (pix > 0) {
 pixrow[i] = 1;
 break;
 }
 }
 }
 // 對數組進行濾波,減少突變概率
 for (int i = 2; i < roi_col - 1 - 2; i++) {
 if ((pixrow[i - 1] + pixrow[i - 2] + pixrow[i + 1] + pixrow[i + 2]) >= 3) {
 pixrow[i] = 1;
 }
 else if ((pixrow[i - 1] + pixrow[i - 2] + pixrow[i + 1] + pixrow[i + 2]) <= 1) {
 pixrow[i] = 0;
 }
 }

之后記錄像素為 0 和 1 所連續的長度來計算字符的寬度,最后用寬度的大小來篩選字符。

// 確認字符位置
 int count = 0;
 bool flage = false;
 for (int i = 0; i < roi_col - 1; i++) {
 pix = pixrow[i];
 if (pix == 1 && !flage) {
 flage = true;
 position1[count] = i;
 continue;
 }
 if (pix == 0 && flage) {
 flage = false;
 position2[count] = i;
 count++;
 }
 if (i == (roi_col - 2) && flage) {
 flage = false;
 position2[count] = i;
 count++;
 }
 }

分割出的結果:

利用OpenCV怎么對車牌的字符進行分割

完整代碼:

#include <iostream> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>

using namespace std;
using namespace cv;

int main() {
 Mat img = imread("number.jpg");
 Mat gray_img;
 // 生成灰度圖像
 cvtColor(img, gray_img, CV_BGR2GRAY);
 // 高斯模糊
 Mat img_gau;
 GaussianBlur(gray_img, img_gau, Size(3, 3), 0, 0);
 // 閾值分割
 Mat img_threadhold;
 threshold(img_gau, img_threadhold, 0, 255, THRESH_BINARY + THRESH_OTSU);
 // 判斷字符水平位置
 int roi_col = img_threadhold.cols, roi_row = img_threadhold.rows, position1[50], position2[50], roi_width[50];
 uchar pix;
 // 確認為 1 的像素
 int pixrow[1000];
 for (int i = 0; i < roi_col - 1; i++) {
 for (int j = 0; j < roi_row - 1; j++) {
 pix = img_threadhold.at<uchar>(j, i);
 pixrow[i] = 0;
 if (pix > 0) {
 pixrow[i] = 1;
 break;
 }
 }
 }
 // 對數組進行濾波,減少突變概率
 for (int i = 2; i < roi_col - 1 - 2; i++) {
 if ((pixrow[i - 1] + pixrow[i - 2] + pixrow[i + 1] + pixrow[i + 2]) >= 3) {
 pixrow[i] = 1;
 }
 else if ((pixrow[i - 1] + pixrow[i - 2] + pixrow[i + 1] + pixrow[i + 2]) <= 1) {
 pixrow[i] = 0;
 }
 }
 // 確認字符位置
 int count = 0;
 bool flage = false;
 for (int i = 0; i < roi_col - 1; i++) {
 pix = pixrow[i];
 if (pix == 1 && !flage) {
 flage = true;
 position1[count] = i;
 continue;
 }
 if (pix == 0 && flage) {
 flage = false;
 position2[count] = i;
 count++;
 }
 if (i == (roi_col - 2) && flage) {
 flage = false;
 position2[count] = i;
 count++;
 }
 }
 // 記錄所有字符寬度
 for (int n = 0; n < count; n++) {
 roi_width[n] = position2[n] - position1[n];
 }
 // 減去最大值、最小值,計算平均值用字符寬度來篩選
 int max = roi_width[0], max_index = 0;
 int min = roi_width[0], min_index = 0;
 for (int n = 1; n < count; n++) {
 if (max < roi_width[n]) {
 max = roi_width[n];
 max_index = n;
 }
 if (min > roi_width[n]) {
 min = roi_width[n];
 min_index = n;
 }
 }
 int index = 0;
 int new_roi_width[50];
 for (int i = 0; i < count; i++) {
 if (i == min_index || i == max_index) {}
 else {
 new_roi_width[index] = roi_width[i];
 index++;
 }
 }
 // 取后面三個值的平均值
 int avgre = (int)((new_roi_width[count - 3] + new_roi_width[count - 4] + new_roi_width[count - 5]) / 3.0);
 // 字母位置信息確認,用寬度來篩選
 int licenseX[10], licenseW[10], licenseNum = 0;
 int countX = 0;
 for (int i = 0; i < count; i++) {
 if (roi_width[i] >(avgre - 8) && roi_width[i] < (avgre + 8)) {
 licenseX[licenseNum] = position1[i];
 licenseW[licenseNum] = roi_width[i];
 licenseNum++;
 countX++;
 continue;
 }
 if (roi_width[i] > (avgre * 2 - 10) && roi_width[i] < (avgre * 2 + 10)) {
 licenseX[licenseNum] = position1[i];
 licenseW[licenseNum] = roi_width[i];
 licenseNum++;
 }
 }

 // 截取字符
 Mat number_img = Mat(Scalar(0));
 for (int i = 0; i < countX; i++) {
 Rect choose_rect(licenseX[i], 0, licenseW[i], gray_img.rows);
 number_img = gray_img(choose_rect);
 imshow("number" + to_string(i), number_img);
 // imwrite("number" + to_string(i) + ".jpg", number_img);
 }
 waitKey(0);
 return 0;
}

關于利用OpenCV怎么對車牌的字符進行分割就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

当雄县| 沙田区| 青州市| 长葛市| 古交市| 靖宇县| 阿拉善左旗| 凤翔县| 十堰市| 台州市| 赣榆县| 普陀区| 乡宁县| 奉新县| 大丰市| 田东县| 北票市| 上栗县| 奈曼旗| 京山县| 齐河县| 栾城县| 上饶市| 木里| 桐庐县| 永丰县| 白河县| 康保县| 岳阳县| 建始县| 项城市| 凌云县| 上高县| 惠安县| 新民市| 二连浩特市| 宁化县| 太原市| 惠来县| 昔阳县| 禄劝|