왼쪽과 같은 b/w 이미지를 오른쪽과 같이 공백을 메우는 방법을 OpenCV로 알아보자.
아울러 아래의 기법도 확실히 알아두기로 하자.
- findNonZero 함수를 이용한 흰픽셀의 좌표얻기
- convexHull 함수를 이용한 어바우트한 윤곽 포인트 획득
이미지를 그레이스케일 변환하여 읽어 들이고 10 을 기준으로 b/w 변환한다.
cv::Mat inputImage = cv::imread("input.jpg", CV_LOAD_IMAGE_GRAYSCALE); cv::threshold(inputImage, inputImage, 10, 255, 0); |
b/w 이미지내에서 흰색픽셀의 좌표를 찾아내서 Mat 안에 보관
cv::Mat nonZeroCoordinates; cv::findNonZero(inputImage, nonZeroCoordinates); |
Mat 구조에서 Point 의 배열로 변환
std::vector<cv::Point> points; for (int i = 0; i < nonZeroCoordinates.total(); i++){ points.push_back(nonZeroCoordinates.at<cv::Point>(i)); } |
흰색의 좌표 포인트 배열로 부터 굴곡을 무시한 어바우트한 외곽 후보 포인트 배열 인덱스를 hull 에 저장
std::vector<int> hull; // 그냥 points 을 써도 되지 않을까? cv::convexHull(cv::Mat(points), hull, false); |
포인트 인덱스가 들어있는 hull 로부터 실제 포인트 좌표를 hullpoints 에 저장
std::vector<cv::Point> hullpoints; int hullcount = (int)hull.size(); for (int i = 0; i < hullcount; i++) { cv::Point pt = points[hull[i]]; hullpoints.push_back(pt); } |
배경이 검은 새로운 이미지 Mat을 만들어 hull 좌표들 안쪽으로 흰색(255)로 채운다.
fillPoly 함수의 두번째 파라미터가 2중 std::vector<std::vector<cv::Point>> 를 원하기 때문에 1차원 배열을 2중 배열형식으로 맞춰주고 있다.
std::vector<std::vector<cv::Point> > fillContAll; fillContAll.push_back(hullpoints); cv::Mat result = cv::Mat::zeros(inputImage.size(), CV_8UC1); cv::fillPoly(result, fillContAll, cv::Scalar(255)); |
'opencv' 카테고리의 다른 글
contour / labelling (0) | 2023.12.07 |
---|---|
b/w 이미지의 칼럼(수직방향)별 검정(=0)픽셀수 카운트 (0) | 2023.12.02 |
cv::Mat 이모저모 (1) | 2023.11.29 |
이미지 회전 (0) | 2023.11.27 |
스캔문서의 기울기 알아보기 - 2 (0) | 2023.11.27 |