영역처리
문제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가 나오면 정답이다.
결과
문제 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를 벗어나지 않도록 처리해줘야 한다.
결과
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;
}
}
...
}
결과
문제 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;
}
}
// ...
}
결과
문제 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 |