본문 바로가기
opencv

스캔문서의 기울기 알아보기

by 꼰대코더 2023. 11. 26.

기울어진 스캔문서 이미지(칼라)가 아래와 같이 있을 경우, 문자인식등을 위해서는 기울기 보정을 해주어야 한다.

이번 기울기 보정의 흐름은 아래와 같다.

그레이 변환 ▶ B/W 변환 ▶ 문자를 흰색으로 변환 ▶ 문자를 두텁게 ▶ 라인을 검출 ▶ 라인의 기울기 평균

 

1. 그레이 변환, B/W 변환

cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
cv::threshold(image, image, 100, 255, cv::THRESH_BINARY);

 

노이즈가 없는 샘플을 사용했기 때문에 위와 같이 간단한 Threshold함수를 사용하였다. 질이 나쁜 이미지를 사용한다면 노이즈제거, otsu 나 adaptive threshold 함수등을 사용해야 할 것 이다.

 

2. 문자를 흰색으로 변환

cv::bitwise_not(image, image);

이미지처리는 흰색(255)를 대상으로 하기때문에 문자를 흰색(바탕을 검은색)으로 변환해 주어야 한다. 

 

3. 문자를 두텁게

cv::dilate(image, image, cv::Mat(), cv::Point(-1, -1), 5);

문자를 이용한 직선라인을 검출하기 위해서는 되도록이면 문자를 두텁게 해주어야 하기 때문에 dilate 함수를 이용하여 5번 확장하도록 한다.

 

4. 라인을 검출

cv::Size size = image.size();
std::vector<cv::Vec4i> lines;
cv::HoughLinesP(image, lines, 1, CV_PI / 180, 100, size.width / 2.f, 20);

라인 검출은 The Probabilistic Hough Line Transform 를 사용한다.  
라인의 길이가 이미지 넓이의 절반 이상(size.width / 2.f)인 것을 대상으로 하고 라인이 도중에 끊어진 경우에는 라인간의 갭이 20 이하인 경우에는 하나의 라인이 되도록 연결하도록 한다.

 

5. 라인의 기울기 평균

double angle = 0.;
unsigned line_count = lines.size();
for (unsigned i = 0; i < line_count; ++i)
{
    angle += atan2((double)lines[i][3] - lines[i][1], (double)lines[i][2] - lines[i][0]);
}
// 래디안각도
angle /= line_count;
// 래디안을 각도로 변환
angle = angle * 180 / CV_PI;

검출된 line 은 왼쪽좌표 x, y = ([0], [1]), 오른쪽좌표 x,y = ([2], [3]) 이므로, 
L1 = [3] - [1]    L2 = [2] - [0]  이 되고 a 각도 = atan(L1/L2) 로 알 수 있다.

  • atan = gives angle value between -90 and 90
  • atan2 = gives angle value between -180 and 180


모든 각도의 평균은 = 2.6922 의 결과가 나왔다.

[라인 기울어짐에 따른 결과 각도]

결과 각도로 보면 좌상에서 우하로 이어진 라인임을 알 수 있다.

나중에 OpenCV를 이용한 회전각도 조정을 하겠지만 

ImageJ  회전 교정을(반대방향이므로 마이너스) 해 보면 아래와 같은 결과가 된다.

※  표준적인 회전은 반시계방향이 + 이지만, ImageJ의 경우는 반시계 방향 회전이 - 이다.

'opencv' 카테고리의 다른 글

이미지 회전  (0) 2023.11.27
스캔문서의 기울기 알아보기 - 2  (0) 2023.11.27
(opencv) 이미지 저장형태, 액서스  (1) 2023.11.25
(opencv) Rectangle 간의 조작에 관해  (1) 2023.11.23
(opencv) pixel access time  (0) 2023.08.09