1. Noise Generation
Y += rand() % Err - (Err >> 1);
2. Salt-and-Pepper Noise
if ((rand() % prob) == 0) Y = 255;
else if ((rand() % prob) == 1) Y = 0;
else Y = Y;
3. Image Restoration
- Noise를 줄이기 위한 이미지 전처리(Denoising)
- 손상된 이미지에서 고품질 이미지를 얻는 작업
4. Median Filter
- 사전정의된 window 내 모든 pixel의 중앙값 제공
- Salt-and-pepper noise에 효과적
5. Mean Filter
- 사전정의된 window 내 모든 pixel의 평균값 제공
- 노이즈 감소 및 평활화
// Filter
int f_size = 3;
// mean filter
unsigned char* filter = (unsigned char*)calloc(f_size * f_size, sizeof(unsigned char));
for (int i = 0; i < f_size * f_size; i++) {
filter[i] = 1.0 / (f_size * f_size);
}
6. Various Filters
Loss-pass filter (Mean filter, Gaussian filter, Weighted average filter, …)
// Filter
int f_size = 3;
// Gussian Filter : 3x3
double G3_filter[] = {1.0/16, 2.0/16, 1.0/16,
2.0/16, 4.0/16, 2.0/16,
1.0/16, 2.0/16, 1.0/16};
for (int i = 0; i < 9; i++) printf("%lf ", G3_filter[i]);
printf("\n");
// Gussian Filter : 5x5
double G5filter[] = {1/273.0, 4/273.0, 7/273.0, 4/273.0, 1/273.0,
4/273.0, 16/273.0, 26/273.0, 16/273.0, 4/273.0,
7/273.0, 26/273.0, 41/273.0, 26/273.0, 7/273.0,
4/273.0, 16/273.0, 26/273.0, 16/273.0, 4/273.0,
1/273.0, 4/273.0, 7/273.0, 4/273.0, 1/273.0};
for (int i = 0; i < 25; i++) printf("%lf ", G5filter[i]);
printf("\n");
7. Combination
한 이미지 내에서 다양한 노이즈에 대한 다중 필터링
이미지에 대한 다중 필터링 (ex: Median Filter, Mean Filter, ...)
A+B 필터, A+B+C 필터, D+C+B+A 필터와 같은 필터 조합
8. Boundary Processing
9. Filter Design
Filter size와 weight design은 MSE와 PSNR 기반으로 설정한다.
10. Experiment
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
#include<math.h>
int main()
{
BITMAPFILEHEADER bmpFile, bmpFile2;
BITMAPINFOHEADER bmpInfo, bmpInfo2;
FILE* inputFile1 = NULL;
inputFile1 = fopen("AICenterY_Noise.bmp", "rb");
fread(&bmpFile, sizeof(BITMAPFILEHEADER), 1, inputFile1);
fread(&bmpInfo, sizeof(BITMAPINFOHEADER), 1, inputFile1);
int width = bmpInfo.biWidth;
int height = bmpInfo.biHeight;
int size = bmpInfo.biSizeImage;
int bitCnt = bmpInfo.biBitCount;
int stride = (((bitCnt / 8) * width) + 3) / 4 * 4,max;
printf("width, height, size, bitCnt, stride : ");
printf("%d, %d, %d, %d, %d\n", width, height, size, bitCnt, stride);
unsigned char* inputImg1 = NULL, * outputImg1 = NULL;
inputImg1 = (unsigned char*)calloc(size, sizeof(unsigned char));
outputImg1 = (unsigned char*)calloc(size, sizeof(unsigned char));
fread(inputImg1, sizeof(unsigned char), size, inputFile1);
unsigned char* Y1 = (unsigned char*)calloc(width * height, sizeof(unsigned char));
// Original Copy
for (int j = 0; j < height; j++)
{
for (int i = 0; i < width; i++)
{
Y1[j * width + i] = inputImg1[j * stride + 3 * i];
}
}
// Padding
// (1) 변수 선언
int padding = 1;
int p_width = width + padding * 2;
int p_height = height + padding * 2;
int p_size = p_width * p_height;
unsigned char* p_Y1 = (unsigned char*)calloc(p_width * p_height, sizeof(unsigned char));
// (2) 원본 이미지 값 입력
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
p_Y1[(j + padding) * p_width + (i + padding)] = Y1[j * width + i];
}
}
// (3) Padding 값 입력
// 꼭짓점
for (int j = 0; j < padding; j++) {
for (int i = 0; i < padding; i++) {
p_Y1[(height + padding + j) * p_width + i] = Y1[(height - 1) * width]; // 좌측 상단
p_Y1[(height + padding + j) * p_width + (width + padding + i)] = Y1[height * width - 1]; // 우측 상단
p_Y1[j * p_width + i] = Y1[0]; // 좌측 하단
p_Y1[j * p_width + (width + padding + i)] = Y1[width - 1]; // 우측 하단
}
}
// 모서리
for (int p = 0; p < padding; p++) {
for (int i = 0; i < width; i++) {
p_Y1[p * p_width + (i + padding)] = Y1[i]; // 상
p_Y1[(p + width + padding) * p_width + (i + padding)] = Y1[(height - 1) * width + i]; // 하
}
}
for (int p = 0; p < padding; p++) {
for (int j = 0; j < height; j++) {
p_Y1[(j + padding) * p_width + p] = Y1[j * width]; // 좌
p_Y1[(j + padding) * p_width + (width + padding) + p] = Y1[(j + 1) * width - 1]; // 우
}
}
// Filter
int f_size = 3;
// (1) mean filter
unsigned char* filter = (unsigned char*)calloc(f_size * f_size, sizeof(unsigned char));
for (int i = 0; i < f_size * f_size; i++) {
filter[i] = 1.0 / (f_size * f_size);
}
// (2) Gussian Filter : 3x3
double G3_filter[] = {1.0/16, 2.0/16, 1.0/16,
2.0/16, 4.0/16, 2.0/16,
1.0/16, 2.0/16, 1.0/16};
for (int i = 0; i < 9; i++) printf("%lf ", G3_filter[i]);
printf("\n");
// (3) Gussian Filter : 5x5
double G5filter[] = {1/273.0, 4/273.0, 7/273.0, 4/273.0, 1/273.0,
4/273.0, 16/273.0, 26/273.0, 16/273.0, 4/273.0,
7/273.0, 26/273.0, 41/273.0, 26/273.0, 7/273.0,
4/273.0, 16/273.0, 26/273.0, 16/273.0, 4/273.0,
1/273.0, 4/273.0, 7/273.0, 4/273.0, 1/273.0};
for (int i = 0; i < 25; i++) printf("%lf ", G5filter[i]);
printf("\n");
// (4) Filtering
double* sumf;
unsigned char* Y2 = (unsigned char*)calloc(width * height, sizeof(unsigned char));
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
sumf = 0;
for (int k = 0; k < f_size; k++) {
for (int l = 0; l < f_size; l++) {
sumf += G3_filter[k * f_size + l] * p_Y1[(j + k) * p_width + (i + l)];
}
}
Y2[j * width + i] = sumf;
}
}
// Evaluation
double mse = 0, psnr;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
mse += (double)((Y2[j * width + i] - Y1[j * width + i]) * (Y2[j * width + i] - Y1[j * width + i]));
}
}
mse /= (width * height);
psnr = mse != 0.0 ? 10.0 * log10(255 * 255 / mse) : 99.99;
printf("MSE = %.2lf\nPSNR = %.2lf dB\n", mse, psnr);
// Output
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
outputImg1[j * stride + 3 * i + 0] = (unsigned char)(Y2[j * width + i]>255 ? 255 : (Y2[j * width + i]< 0 ? 0 : Y2[j * width + i]));
outputImg1[j * stride + 3 * i + 1] = (unsigned char)(Y2[j * width + i] > 255 ? 255 : (Y2[j * width + i] < 0 ? 0 : Y2[j * width + i]));
outputImg1[j * stride + 3 * i + 2] = (unsigned char)(Y2[j * width + i] > 255 ? 255 : (Y2[j * width + i] < 0 ? 0 : Y2[j * width + i]));
}
}
FILE* outputFile1 = fopen("Output.bmp", "wb");
fwrite(&bmpFile, sizeof(BITMAPFILEHEADER),1,outputFile1);
fwrite(&bmpInfo, sizeof(BITMAPINFOHEADER), 1, outputFile1);
fwrite(outputImg1, sizeof(unsigned char), size, outputFile1);
// Free
free(inputImg1);
free(outputImg1);
free(Y1);
free(Y2);
free(p_Y1);
fclose(inputFile1);
fclose(outputFile1);
}
'Computer Science > 영상처리' 카테고리의 다른 글
(C/C++) Histogram (0) | 2024.04.02 |
---|---|
(C/C++) Quality Evaluation(PSNR) (0) | 2024.03.27 |
(C/C++) Pixel Operation (0) | 2024.03.27 |
(C/C++) Color Model (0) | 2024.03.27 |
(C/C++) Image Format (0) | 2024.03.27 |