본문 바로가기
IT

[openCV / C++] Image Thresholding 이미지 처리하기, 이미지 이진화

by 배애앰이 좋아 2021. 1. 4.
반응형

Thresholding :  In digital image processing, thresholding is the simplest method of segmenting images. From a grayscale image, thresholding can be used to create binary images.

 

위 정의 : 가장 간단한 임계 값 방법으로 이미지 강도가 특정 기준 T 보다 클 경우 흰색 픽셀로 대체 작을 경우 검은색 픽셀로 대체합니다. 결과적으로 이미지는 흰색 또는 흰색으로 색깔을 가지게 됩니다.

 

임계값 정의 : 임계란 '경계'와 비슷한 개념으로, 어떤 변화가 나타나기 시작하는 지점이다. 미분간으한 함수에서 나타나는 변화는 일반적으로 증가, 감소 양상이 달라지는 경우를 말하며, 그러한 경우가 나타나기 위해서는 미분계수기 0이 되는 경우이다.

 

일부 코드 : Thresholding 하는 코드

 

 

void computeThresohoding(IplImage *img, IplImage *cpimg, double th = 100) {
	//th 임계값
	for (int i = 0; i < img->width; i++) {
		for (int j = 0; j < img->height; j++) {
			auto c = cvGet2D(img, j, i);
			auto b = (c.val[0] + c.val[1] + c.val[2]) / 3.0;
			if (b > th) {
				cvSet2D(cpimg, j, i, CV_RGB(255, 255, 2550));
			}
		}
	}
}

 

auto c = cvGet2D(img, j, i); 를 통해 각 좌표에 픽셀 색깔 값을 가져옵니다. 그 후에 RGB 값을 더해서 3으로(RGB 3가지 색상을 더한 것임으로) 나눠주면 해당 픽셀 값의 밝기 값이 나오게 됩니다. 이때의 임의의 사용자가 정한 기준 th(임계값)을 가져와서 해당 픽셀 밝기 값이 th보다 높을 경우 흰색으로 그렇지 않을 경우 검은색으로 만들어줍니다. 위에 경우 이미 배경으로 검은 색으로 만들어주었기 때문에 흰색을 경우만 if문 처리로 바꿔줍니다.

 

아래 풀 코드 :

 

#include <stdio.h>
#include "opencv2/opencv.hpp"

IplImage *merge(IplImage *img, IplImage *cpimg)
{
	IplImage *bimg = cvCreateImage(cvSize(img->width * 2, img->height), 8, 3);
	for (int i = 0; i < img->width; i++)
	{
		for (int j = 0; j < img->height; j++)
		{
			auto color1 = cvGet2D(img, j, i);
			auto color2 = cvGet2D(cpimg, j, i);
			cvSet2D(bimg, j, i, color1);
			cvSet2D(bimg, j, img->width + i, color2);
		}
	}
	return bimg;
}

void computeThresohoding(IplImage *img, IplImage *cpimg, double th = 100) {
	//th 임계값
	for (int i = 0; i < img->width; i++) {
		for (int j = 0; j < img->height; j++) {
			auto c = cvGet2D(img, j, i);
			auto b = (c.val[0] + c.val[1] + c.val[2]) / 3.0;
			if (b > th) {
				cvSet2D(cpimg, j, i, CV_RGB(255, 255, 2550));
			}
		}
	}
}

int main(void)
{
	IplImage *img = cvLoadImage("img//img3.jpg");
	IplImage *cpimg = cvCreateImage(cvGetSize(img), 8, 3);
	
	cvSet(cpimg, CV_RGB(0, 0, 0));
	computeThresohoding(img, cpimg);
		
	auto bimg = merge(img, cpimg);
	cvShowImage("My Window", bimg);

	cvWaitKey();
	cvDestroyAllWindows();
	cvReleaseImage(&img);
}

 

merge 함수 경우 원본 이미지, 만든 이미지를 합쳐서 window 창을 띄우게 하여 비교할 수 있게 만들어주는 함수이다.

 

th = 100

 

위 사진의 기준 th을 100으로 했을 경우,

 

th = 100

 

위 사진의 기준 th을 100으로 했을 경우,

 

th = 200

 

위 사진의 기준 th을 200으로 했을 경우,

 

th = 55

 

위 사진의 기준 th을 55으로 했을 경우,

 

보시다싶이 임계값 th이 높을수록 검은색이 많이 나오며, 낮을수록 흰색이 많이 나오는 것을 확인할 수 있다.

 

응용편 : 흰색, 검은색이 아닌 그 외 좀 더 멀티적인 색깔로 구현하는 방법

 

void mutiTresohoding(IplImage *img, IplImage *cpimg) {
	//th 임계값
	for (int i = 0; i < img->width; i++) {
		for (int j = 0; j < img->height; j++) {
			auto c = cvGet2D(img, j, i);
			auto b = (c.val[0] + c.val[1] + c.val[2]) / 3.0;
			if (b < 43) {
				cvSet2D(cpimg, j, i, CV_RGB(0, 0, 0));
			}
			else if (b < 128) {
				cvSet2D(cpimg, j, i, CV_RGB(85, 85, 85));
			}
			else if (b < 213) {
				cvSet2D(cpimg, j, i, CV_RGB(170, 170, 170));
			}
			else {
				cvSet2D(cpimg, j, i, CV_RGB(255, 255, 255));
			}
		}
	}
}

 

조건문을 통해서 기준을 여러 개 줘 흰색, 회색, 검은색 등 총 4개의 색깔로 나타나도록 구현

 

결과 이미지 1

 

결과 이미지 2

 

위 코드를 조건문이 아닌 더 효율적인 코드 작성법 :

 

void mutiTresohoding2(IplImage *img, IplImage *cpimg) {
	
	double thresohold[5] = { 0.8, 30.0, 130.0, 170.0, 255.0 };

	for (int i = 0; i < img->width; i++) {
		for (int j = 0; j < img->height; j++) {
			auto c = cvGet2D(img, j, i);
			auto b = (c.val[0] + c.val[1] + c.val[2]) / 3.0;
			int id = (int)(b / 255 * 5);
			auto final_c = thresohold[id];
			cvSet2D(cpimg, j, i, CV_RGB(final_c, final_c, final_c));
		}
	}
}

 

위 코드 결과 이미지 1

 

위 코드 결과 이미지 2

반응형

댓글