[영상통신] 영역처리

영역처리

문제1 : Gonzales & Woods Threshold 결정

grayscale Lenna를 이용하여 Gonzales & Woods algorithm을 이용하여 임계치 T를 구한 후, [0, 255]의 binary image를 얻으시오.

*iterative 반복문으로 for문이 필요하다.

임계값(Threshold) 자동 결정 방법(Gonzales - Woods)

1. 임계값 T의 초기값을 추정한다. (제안된 추정 값은 영상에서 밝기값의 최소값과 최대값 사이의 중간점) 

>> 초기 임계값 T0 = (Ymax + Ymin) / 2

2. T로 이진화(binarization)한다. 그 결과는 밝기값이 T보다 큰 화소들로 구성된 그룹(G1)과 밝기값이 T보다 작은 화소들로 구성된 그룹(G2)의 화소들로 나누어진다.

3. 그룹 G1과 G2에 대하여 화소들의 밝기의 평균값 M1, M2를 구한다.

4. 연속적으로 다음과 같은 새로운 임계값을 계산한다.

>> 연속적인 반복에서 임계 값의 변화가 미리 정의된 오차 ε보다 작을 때까지 2단계에서 4단계까지 반복한다.

 

정답 코드

#include <iostream>

...

int main()
{
    ...
    
	// Write your code here 
    
	// T0 구하기
	int MAX = 0;
	int MIN = 255;
	for (int i = 0; i < Height; i++)
	{
		for (int j = 0; j < Width; j++)
		{
			int cur = *(YBuf + i * Width + j);
			if (cur > MAX)
				MAX = cur;
			if (cur < MIN)
				MIN = cur;
		}
	}

	// Gonzales-Woods
	int T0 = (MAX + MIN) / 2;
	int T;
	int epsilon = 5;
	while (true)
	{
		int G1 = 0;
		int C1 = 0; // G1 그룹의 멤버 수
		int G2 = 0;
		int C2 = 0; // G2 그룹의 멤버 수
		for (int i = 0; i < Height; i++)
		{
			for (int j = 0; j < Width; j++)
			{
				int cur = *(YBuf + i * Width + j);
				if (cur >= T0)
				{
					G1 += cur;
					C1++;
				}
				else
				{
					G2 += cur;
					C2++;
				}
			}
		}
        
		// M1, M2로 T 구하기
		T = (G1 / C1 + G2 / C2) / 2;
		if (abs(T0 - T) < epsilon)
			break;
		else
			T0 = T;
	}

	// 이진화
	for (int i = 0; i < Height; i++)
	{
		for (int j = 0; j < Width; j++)
		{
			int cur = *(YBuf + i * Width + j);
			if (cur >= T) *(YBuf + i * Width + j) = 255;
			else *(YBuf + i * Width + j) = 0;
		}
	}
	printf("T %d \n", T);

    ...
}

...

T는 122가 나오면 정답이다.

 

결과

좌 : 원본, 우 : binary Image

 

 

문제 2 : 딥러닝에서 사용하는 미분식

다음 식 f(x)에서 x=2.7에서의 미분값을 구해보자.

 

식을 직접 미분하면

이고,

 

미분 식은 다음과 같다.

 

x = 2.7;

epsilon=0.001;

으로 미분 식(D1)과 직접 미분한 식(D2)에 대입해 결과값을 얻어보자.

 

정답 코드

#include <iostream>

...

int main()
{
    ...
    
	// Write your code here 
    
	float x = 2.7;
	float epsilon = 0.001;
	float fx = x * x - 3 * x + 1;
	float fxe = (x + epsilon) * (x + epsilon) - 3 * (x + epsilon) + 1;
	float D1 = (fxe - fx) / epsilon;
	float D2 = 2 * x - 3;
	printf("\n\n D1 = %f, D2 = %f\n\n", D1, D2);

    ...
}

 

결과

위 사진과 같이 D1 = 2.401, D2 = 2.4가 나오면 정답이다.

 

문제 3 : Convolution Filter(합성곱 필터)

Grayscale 영상에 convolution Filter를 적용한 출력영상을 얻으세요.

 

1. Average Filter

정답 코드

#include <iostream>

...

int main()
{

	BYTE* Out = new BYTE[Width * Height];  // Grayscale Image

    	...

	// Write your code here 
	memcpy(Out, YBuf, Width * Height * 3);

	static int Filter[3][3] = { {1, 1, 1}, {1, 1, 1} , {1, 1, 1} };

	for (int i = 1; i < Height - 1; i++)
	{
		for (int j = 1; j < Width - 1; j++)
		{
			int sum = 0;
			for (int dy = -1; dy <= 1; dy++)
			{
				for (int dx = -1; dx <= 1; dx++)
				{
					int newY = i + dy;
					int newX = j + dx;
					sum += (*(YBuf + newY * Width + newX)) * Filter[dy + 1][dx + 1];
				}
			}

			*(Out + i * Width + j) = sum / 9;
		}
	}

    	...
}

필터 영역의 값을로 필터와 계산 후 마지막에 출력 배열에 저장해준다.

기존 이미지에 저장하면 다음 픽셀을 계산할 때 이전 픽셀의 값이 바뀌였기 때문에 결과가 틀리게 된다. 

 

결과

좌 : 원본 / 우 : 평균 필터

 

 

2. Sharpening

정답 코드

#include <iostream>

...

int main()
{

	BYTE* Out = new BYTE[Width * Height];  // Grayscale Image

    	...

	// Write your code here 
	memcpy(Out, YBuf, Width * Height * 3);

	static int Filter[3][3] = { {-1, -1, -1}, {-1, 9, -1} , {-1, -1, -1} };
	
	for (int i = 1; i < Height - 1; i++)
	{
		for (int j = 1; j < Width - 1; j++)
		{
			int sum = 0;
			for (int dy = -1; dy <= 1; dy++)
			{
				for (int dx = -1; dx <= 1; dx++)
				{
					int newY = i + dy;
					int newX = j + dx;
					sum += (*(YBuf + newY * Width + newX)) * Filter[dy + 1][dx + 1];
				}
			}
			if (sum > 255) sum = 255;
			if (sum < 0) sum = 0;

			*(Out + i * Width + j) = sum;
		}
	}

    	...
}

* sum의 값이 0~255를 벗어나지 않도록 처리해줘야 한다.

 

결과

좌 : 원본 / 우 : Sharpening filter

 

 

3. Embossing

정답 코드

#include <iostream>

...

int main()
{

	BYTE* Out = new BYTE[Width * Height];  // Grayscale Image

    	...

	// Write your code here 
	memcpy(Out, YBuf, Width * Height * 3);

	static int Filter[3][3] = { {-1, 0, 0}, {0, 0, 0} , {0, 0, 1} };
	
	for (int i = 1; i < Height - 1; i++)
	{
		for (int j = 1; j < Width - 1; j++)
		{
			int sum = 0;
			for (int dy = -1; dy <= 1; dy++)
			{
				for (int dx = -1; dx <= 1; dx++)
				{
					int newY = i + dy;
					int newX = j + dx;
					sum += (*(YBuf + newY * Width + newX)) * Filter[dy + 1][dx + 1];
				}
			}
			sum += 128;
			if (sum > 255) sum = 255;
			if (sum < 0) sum = 0;

			*(Out + i * Width + j) = sum;
		}
	}

    	...
}

 

결과

좌 : 원본 / 우 : Embossing filter

 

 

문제 4 : Sobel Edge Operator


1. 두 개의 filter로부터 픽셀마다2개의 합성곱 출력값 Hx, Hy를 구한다.

2. Edge strength Hm을 계산한다.

3. 임계값 T로 Edge Map을 bmp로 저장한다. (T 값은 사용자가 정함)

* 경계값 처리는 하지 않음.

 

정답 코드

#include <iostream>

// ...

int main()
{

	BYTE* Out = new BYTE[Width * Height];  // Grayscale Image
    
    
	// ...

	// Write your code here 
	memcpy(Out, YBuf, Width * Height);
	static int Fy[3][3] = { {-1,0, 1}, {-2, 0, 2} , {-1, 0, 1} };
	static int Fx[3][3] = { {-1,-2, -1}, {0,0, 0} , {1, 2, 1} };
	for (int i = 1; i < Height - 1; i++) {
		for (int j = 1; j < Width - 1; j++) {

			int sumX = 0;
			int sumY = 0;
			for (int dy = -1; dy <= 1; dy++) {
				for (int dx = -1; dx <= 1; dx++) {
					int newY = i + dy;
					int newX = j + dx;
					sumX += (*(YBuf + newY * Width + newX)) * Fx[dy + 1][dx + 1];
					sumY += (*(YBuf + newY * Width + newX)) * Fy[dy + 1][dx + 1];
				}
			}

			int sum = sqrt((double)(sumX * sumX + sumY * sumY));
		
			int T = 100;
			if (sum >= T) sum = 255;
			if (sum < T) sum = 0;

			*(Out + i * Width + j) = sum;
		}
	}
	
	// ...

}

 

결과

좌 : T = 100, 우 : T = 200

 

문제 5 : Upsampling using NNI (nearest neighbor interpolation) (1-D)


1. 크기 10의 1-D 영상데이터를 선언한다.

int input_1D[10] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};

2. scale=1.6배 확대하면 얻어지는 크기 16의 출력 배열 선언

int output_1D[16] = {0, };

3. NNI. 좌표값은 반올림해 역방향 사상으로 각 출력 배열의 원소를 채운다. (overflow 처리 필요함)

 

정답 코드

#include <iostream>

// ...

int main()
{

	BYTE* Out = new BYTE[Width * Height];  // Grayscale Image
    
    
	// ...

	// Write your code here 
	int input_1D[10] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
	int output_1D[16] = { 0, };

	for (int y = 0; y < 17; y++)
	{
		double x = y / 1.6;
		int xi = (int)(x + 0.5);
		output_1D[y] = input_1D[xi];
	}

	// 출력
	printf("\n\n");
	for (int i : output_1D)
	{
		printf("%d ", i);
	}
	printf("\n\n");

	
	// ...

}

 

결과

 

'공부 > 영상통신' 카테고리의 다른 글

[영상통신] Bitwise Operation  (0) 2024.12.15
[영상통신] 압축 기술  (0) 2024.12.15
[영상통신] Pixel 처리  (0) 2024.12.15