사용 환경
Visual Studio 2022
OpenCV 4.5.4
Tesseract-OCR 5.0.1
OpenCV와 Tesseract를 사용해서 자동차 번호판을 인식하는 방법입니다.
OpenCV 설치 방법
2022.03.11 - [OpenCV] - Visual Studio에서 OpenCV 설치하기
Tesseract 설치 방법
2022.03.11 - [OpenCV] - Visual Studio에서 Tesseract-OCR 사용해보기
자세한 코드는 https://github.com/kangsunghyun111/Car-license-plate-recognition-using-tesseract-OCR 에 있습니다.
이미지 처리부터 출력까지의 과정을 크게 세 단계로 나눠 볼 수 있습니다.
1. 자동차 번호판의 위치 찾기
원본 이미지
이미지를 회색으로 바꿉니다.
cvtColor(image2, image2, COLOR_BGR2GRAY);
이미지를 가우시안 블러 처리해줍니다. 이미지를 흐리게 만들어서 노이즈를 줄여줍니다.
GaussianBlur(image2, image2, Size(5,5), 0);
이미지를 canny 처리해서 윤곽선만 남깁니다.
Canny(image2, image2, 100, 300, 3);
윤곽선을 찾고 직사각형을 씌웁니다.
우리가 원하는 건 번호판 모양의 윤곽이므로 적당한 비율과 넓이를 설정해서 걸러냅니다.
// Finding contours
findContours(image2, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
vector<vector<Point> > contours_poly(contours.size());
vector<Rect> boundRect(contours.size());
vector<Rect> boundRect2(contours.size());
// Bind rectangle to every rectangle.
for (int i = 0; i < contours.size(); i++) {
approxPolyDP(Mat(contours[i]), contours_poly[i], 1, true);
boundRect[i] = boundingRect(Mat(contours_poly[i]));
}
drawing = Mat::zeros(image2.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++) {
ratio = (double)boundRect[i].height / boundRect[i].width;
// Filtering rectangles height/width ratio, and size.
if ((ratio <= 2.5) && (ratio >= 0.5) && (boundRect[i].area() <= 700) && (boundRect[i].area() >= 100)) {
drawContours(drawing, contours, i, Scalar(0, 255, 255), 1, 8, hierarchy, 0, Point());
rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), Scalar(255, 0, 0), 1, 8, 0);
// Include only suitable rectangles.
boundRect2[refinery_count] = boundRect[i];
refinery_count += 1;
}
}
boundRect2.resize(refinery_count); // Resize refinery rectangle array.
표시된 직사각형 중에 번호판만 남기고 나머지는 걸러냅니다.
2. 이미지 회전 및 번호판만 남기기
Tesseract-OCR의 인식률을 높이기 위해 번호판을 x축에 평행하도록 회전시킵니다.
// Image processing is performed to increase the recognition rate of tesseract-OCR
// The first is to rotate the tilted car plate straight
Mat cropped_image;
image.copyTo(cropped_image);
Point center1 = (carNumber[0].tl() + carNumber[0].br()) * 0.5; // Center of the first number
Point center2 = (carNumber[carNumber.size()-1].tl() + carNumber[carNumber.size() - 1].br()) * 0.5; // Center of the last number
int plate_center_x = (int)(center1.x + center2.x) * 0.5; // X-coordinate at the Center of car plate
int plate_center_y = (int)(center1.y + center2.y) * 0.5; // Y-coordinate at the Center of car plate
// To calculate the height
int sum_height=0;
for (int i = 0; i < carNumber.size(); i++)
sum_height += carNumber[i].height;
plate_width = (-center1.x + center2.x + carNumber[carNumber.size() - 1].width) * 1.05; // Car plate width with some paddings
plate_height = (int)(sum_height / carNumber.size()) * 1.2; // Car plate height with some paddings
delta_x = center1.x - center2.x;
delta_y = center1.y - center2.y;
// Roatate car plate
double angle_degree = (atan(delta_y / delta_x))*(double)(180/3.141592);
Mat rotation_matrix = getRotationMatrix2D(Point(plate_center_x, plate_center_y), angle_degree, 1.0);
warpAffine(cropped_image, cropped_image, rotation_matrix, Size(original_width, original_height));
그 다음 번호판의 중심 좌표와 폭, 높이를 이용해서 번호판만 추출합니다.
3. 결과물 인식하기
Tesseract api를 psm 7, oem 0 으로 설정해줍니다.
psm을 7로 설정하는 이유는 번호판이 한 줄로 이루어져있기 때문입니다.
// Initialize tesseract-ocr with Korean, oem is 0
if (api->Init("C:\\Program Files\\tesseract-OCR\\tessdata", "kor3",tesseract::OEM_TESSERACT_ONLY)) {
fprintf(stderr, "Could not initialize tesseract.\n");
exit(1);
}
// Set page segmentation mode to PSM_SINGLE_LINE(7), it assumes there is only one line
api->SetPageSegMode(tesseract::PSM_SINGLE_LINE);
정규표현식을 사용해서 번호판 형식에 맞는 문자열을 출력합니다.
// Extract "12가3456" or "123가4567"
regex re("\\d{2,3}\\W{2}\\s{0,}\\d{4}");
smatch match;
if (regex_search(text, match, re)) {
return match.str();
}
결과
참고한 사이트
https://mind3002.blogspot.com/2016/01/cc-opencv-license-plates-recognition.html
https://tesseract-ocr.github.io/tessdoc/ImproveQuality.html
https://opencv-python.readthedocs.io/en/latest/doc/09.imageThresholding/imageThresholding.html
https://docs.opencv.org/2.4.9/modules/imgproc/doc/imgproc.html
https://maxtime1004.tistory.com/37?category=971805
https://jay1127.github.io/cpp/5-Use-Tesseract-API/
기록용입니다.
'OpenCV' 카테고리의 다른 글
Visual Studio와 Arduino사용해서 간단한 주차 시스템 구현하기 (0) | 2022.03.25 |
---|---|
Visual Studio에서 OpenCV 설치하기 (0) | 2022.03.11 |
Visual Studio에서 Tesseract-OCR 사용해보기 (2) | 2022.03.11 |