아이디어
1. 흑백으로 변환하여 contour 를 실시
2. approxPolyDP로 contour 결과로 부터 꼭지점이 4개(4개의 코너)인 것 중 가장 면적이 넓은 contour를 기억
3. boundingRect 로 사각형의 좌표와 사이즈를 추출
주의)
노이즈가 심한 경우 contour결과에 영향을 줄 수 있으니 필터링에 신경을 더 써야 할 경우가 있다.
번호판 보다 더 큰 contour가 있을 수 있으니 고정 이미지라면 정해진 사이즈에 근접한 contour 를 선택하면 된다.
cv::Mat img = cv::imread("d:\\plate.jpg"); # gray 변환 cv::Mat gray; cv::cvtColor(img, gray, CV_BGR2GRAY); # 노이즈를 완화해 주자 cv::GaussianBlur(gray, gray, cv::Size(3, 3), 0.0); # 흑백이미지 변환 -> 사진이면 빛의 영향으로 밝기가 고르지 못하니 11x11 내의 이진화 방법을 사용 cv::Mat thresh; cv::adaptiveThreshold(gray, thresh, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, 11, 2); # contour 실시 -> https://eldercoder.tistory.com/63 참조 std::vector<std::vector<cv::Point>> contours; std::vector<cv::Vec4i> hierarchy; # 번호판외부에도 닫혀진 contour가 있을 수 있으니 이번엔 모든 contour를 뽑아내자 ( CV_RETR_LIST ) cv::findContours(thresh, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); # 최대 면적을 같은 contour index 를 기억하기 위한 변수 double maxArea = 0.0; size_t maxAreaIdx = 0; for (size_t i = 0; i < contours.size(); i++) { std::vector<std::vector<cv::Point>> points; # contour결과의 포인트들로 부터 대충의 형태를 추출(조건은 1% 이상 변형되지 않을 것) cv::approxPolyDP(cv::Mat(contours[i]), points, 0.01 * cv::arcLength(contours[i], true), true); # 꼭지점이 4개 if (points.size() == 4) { double area = cv::contourArea(contours[i]); if (area > maxArea ) { maxArea = area; maxAreaIdx = i; } } } # 해당 contour 로 부터 좌표와 사이즈 추출 cv::Rect rect = cv::boundingRect(contours[ maxAreaIdx]); cv::rectangle(img, rect, cv::Scalar(0, 0, 255), 3); cv::imwrite("d:\\result.png", img); return 0; |
Python
import numpy as np import cv2 import pytesseract import matplotlib.pyplot as plt img = cv2.imread('/home/muthu/Documents/3r9OQ.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2) contours,h = cv2.findContours(thresh,1,2) largest_rectangle = [0,0] for cnt in contours: approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True) if len(approx)==4: area = cv2.contourArea(cnt) if area > largest_rectangle[0]: largest_rectangle = [cv2.contourArea(cnt), cnt, approx] x,y,w,h = cv2.boundingRect(largest_rectangle[1]) roi=img[y:y+h,x:x+w] plt.imshow(roi, cmap = 'gray') plt.show() |
'opencv' 카테고리의 다른 글
close contours (convexHull 사용) (0) | 2025.02.16 |
---|---|
스캔 이미지 중 여러 영수증 분리하기 (0) | 2025.02.15 |
Color를 Grayscale 로 변환 (커스텀 비율) (0) | 2025.02.14 |
C# 와 C++/CLI Dll 사이의 이미지 전달 (0) | 2025.02.10 |
(opencv) 이미지위의 직선상의 픽셀위치 구하기 (0) | 2025.02.08 |