안녕하세요 열코입니다!

OpenCV로 영상처리 및 패턴인식을 공부하는 동안 가장 기본적인 자동차 번호판 인식 프로그램을 

간단하게 제작해 보았습니다.


* 개발 환경

개발 툴 : Visual Studio 2017

개발 언어 : C#


* 기능

- IplImage Load(불러오기) 및 Save(저장)

- Web Image Load 및 Save

- Image GrayScale(흑백)

- Image Binary(이진화)

- Image CannyEdge(에지 검출)

- Templet Match 및 ROI(관심 영역 추출)

- Mouse Drag Event로 ROI

- Tesseract-OCR(API)

- OpenALPR(API)


* 소스 코드

전체 소스코드는 300줄가량 되며, 부분 소스코드만 공개하고 설명합니다.


- Binary 함수


1
2
3
4
5
6
7
8
9
IplImage gray = new IplImage(src.Size, BitDepth.U8, 1); // GrayScale 수행
 
Cv.CvtColor(src, gray, ColorConversion.BgrToGray);
 
IplImage bina = new IplImage(src.Size, BitDepth.U8, 1);
 
int temp = trackBar1.Value * 20// track bar 값을 받아와 적절한 수치로 변환
 
Binarizer.SauvolaFast(gray, bina, temp, 0.264); // Sauvola 방법으로 이진화 수행
cs



- Tesseract 함수


1
2
3
4
5
6
7
8
9
Bitmap img = new Bitmap(pictureBoxIpl2.Image);  
 
var ocr = new TesseractEngine("./tessdata""kor", EngineMode.Default);  
 
// ./tessdata : tesseract 문자 인식 훈련 데이터, kor : 한글 or eng : 영문
 
var texts = ocr.Process(img); 
 
textBox1.AppendText(texts.GetText());
cs




- OpenALPR


1
2
3
4
5
6
7
8
9
10
11
12
13
Task<string> recognizeTask = Task.Run(() => ProcessImage(savePath));
 
recognizeTask.Wait();
 
string task_result = recognizeTask.Result;
 
string result = task_result.Split(':')[11].Split(',')[0];
 
result = result.Replace("\"""");
 
result = result.Trim();  // 결과 값을 적절히 파싱
 
textBox1.AppendText(result);
cs





* 실행 화면

프로그램을 실행하면 아래 사진과 같은 화면이 실행됩니다.



Load Image를 눌러 로컬 컴퓨터 내 이미지를 불러오거나 Capture를 눌러 연결된 카메라로 사진을 불러올 수 있습니다. 먼저 Capture를 눌러 사진을 찍어보겠습니다.




제 책상 위의 아이폰을 한번 찍어봤습니다...

캡처된 이미지를 불러오기 성공했다는 로그가 뜨고 화면에 이미지를 불러옵니다.

이 사진은 딱히 패턴인식할 사진이 아니므로 Load Image로 자동차 사진을 불러오겠습니다.



자동차 이미지를 불러왔습니다.

자동차 번호판을 인식해야 하는데 먼저 전처리 과정을 거쳐야 인식률이 많이 높아집니다.

(사진 선명도 및 노이즈를 제거하기 위해 처리하는 과정입니다.)



- GrayScale은 RGB 컬러사진은 흑백 사진으로 변환해주는 버튼입니다.

- CannyEdge는 사진의 Edge(모서리) 영역만 감지하여 나타내주는 버튼입니다.

- Init은 작업한 사진을 초기화하는 버튼입니다.

- Binary Degree는 Track Bar로 구현했습니다. 수치의 degree( 정도) 값에 의해 Binary(이진화) 처리를 해줍니다.



120 degree로 Binary 처리한 결과입니다.

번호판 부분이 선명하게 처리되었습니다.



마우스 이벤트를 이용하여 마우스 드래그를 하여 마우스 X, Y좌표를 받아온 후 좌표 크기만큼 잘라서 따로 표시해줍니다. (패턴 인식 알고리즘 속도 향상을 위해)



패턴인식 알고리즘은 2가지를 사용했습니다.

Logic 1은 Open Library인 Tesseract 알고리즘을 사용했고,

Logic 2는 OpenALPR API를 사용했습니다.

(OpenALPR은 유료 라이브러리로 2000회 무료로 사용 가능합니다.) 

두 라이브러리 모두 인식률은 상용적으로 사용할 정도로 높진 않았습니다.



하지만 전처리 과정과 알고리즘 수정을 통해 어느 정도 인식률을 높이는 것이 가능합니다.

Logic 1 버튼을 눌러 결과를 확인하니 번호판을 정확히 인식하는 모습입니다.

실행 시간은 두 로직 모두 1~3초 정도 소요합니다. (더 많은 최소화 작업이 필요)  

Templet Match는 미리 저장해 둔 Templet 사진을 통해 기존 사진과 비교하여 번호판을 찾아내는 방법입니다. 번호판 모양이 제각각이기 때문에 인식률이 많이 낮았습니다.



Logic 2(OpenALPR) 실행 결과입니다.

실행 시간은 Logic 1(Tesseract) 조금(0.5초~1초) 더 걸리는 정도였습니다.

OpenALPR 홈페이지에서 데모 프로그램 실행 시 한글 인식이 잘 되는 걸로 확인했는데

소스코드로 구현하니 한글 인식이 안되는 걸로 나옵니다... (아시는 분 댓글로 부탁드립니다)


* 수정

- OpenALPR 한글지원 가능합니다.

PostAsync에서 API주소에 country를 us에서 kr로 변경하면 한글도 인식됩니다.

한글을 unicode로 처리하기 때문에 한글이 \ud638 이런식으로 출력됩니다.

유니코드를 한글로 변경하는 알고리즘을 따로 구현하여 처리하였습니다.


유니코드 한글로 변환하기


또 다른 차량 번호판 인식 결과입니다.



다른 차량 역시 번호판을 잘 인식하는 모습입니다.

위 사진처럼 깨끗하고 깔끔하게 번호판이 나온 경우 따로 전처리 작업을 해주지 않아도 인식하는 모습입니다.


알고리즘 및 전처리 과정을 수정하여 실시간 CCTV에서 번호판 인식이 가능하고, 자율 주행 자동차에서 도로 인식 및 표지판, 신호등을 인식하는 알고리즘을 만들어 볼 수 있겠네요




질문 또는 오타나 잘못된 정보가 있는 경우 댓글로 달아주세요!

공감♡ 버튼을 눌러주시면 더욱 유용하고 좋은 포스팅으로 찾아 뵙겠습니다.






to Top