Как приведенный ниже код на самом деле удаляет шум с изображения? Я пытаюсь понять, что происходит, но не могу понять общую идею. Я попробовал это, и это работает (но не очень хорошо). Пожалуйста, дайте приблизительное объяснение. Спасибо.
void averageFilter(PIXEL_ARRAY* img, PIXEL_ARRAY* orig_img, int N)
{
int i, j, n, m;
int red_avg, blue_avg, green_avg;
int radius, out_of_bounds, idx, curr_idx;
int32_t pixel;
if (N % 2 == 0) {
printf("ERROR: Please use an odd sized window\n");
exit(1);
}
radius = N / 2;
for (i = 0; i < img->sizeY; i++) {
for (j = 0; j < img->sizeX; j++) {
out_of_bounds = 0;
red_avg = 0;
blue_avg = 0;
green_avg = 0;
for (n = i - radius; n <= i + radius; n++) {
for (m = j - radius; m <= j + radius; m++) {
if (n < 0 || m < 0 || n >= img->sizeY || m >= img->sizeX) {
out_of_bounds++;
continue;
}
idx = m + n * img->sizeX;
/* Shift, mask and add */
red_avg += ((orig_img->data[idx] >> 16) & 0xFF);
green_avg += ((orig_img->data[idx] >> 8) & 0xFF);
blue_avg += (orig_img->data[idx] & 0xFF);
}
}
/* Divide the total sum by the amount of pixels in the window */
red_avg /= (N * N - out_of_bounds);
green_avg /= (N * N - out_of_bounds);
blue_avg /= (N * N - out_of_bounds);
/* Set the average to the current pixel */
curr_idx = j + i * img->sizeX;
pixel = (red_avg << 16) + (green_avg << 8) + blue_avg;
img->data[curr_idx] = pixel;
}
}
}
Код исследует окрестности каждого пикселя, находит среднее значение каждого компонента R, G, B и записывает их в выходное изображение. Итак, сглаживающий фильтр. Я прокомментировал код:
void averageFilter(PIXEL_ARRAY* img, PIXEL_ARRAY* orig_img, int N)
{
int i, j, n, m;
int red_avg, blue_avg, green_avg;
int radius, out_of_bounds, idx, curr_idx;
int32_t pixel;
if (N % 2 == 0) {
printf("ERROR: Please use an odd sized window\n");
exit(1);
}
radius = N / 2; // distance from pixel to explore
for (i = 0; i < img->sizeY; i++) { // parse each image pixel
for (j = 0; j < img->sizeX; j++) {
out_of_bounds = 0;
red_avg = 0; // init the averages
blue_avg = 0;
green_avg = 0;
for (n = i - radius; n <= i + radius; n++) { // within the area to explore
for (m = j - radius; m <= j + radius; m++) {
if (n < 0 || m < 0 || n >= img->sizeY || m >= img->sizeX) { // off the map?
out_of_bounds++; // count pixels off the map
continue; // and skip the summing
}
idx = m + n * img->sizeX; // locate index of the pixel in source 1D array
/* Shift, mask and add */
red_avg += ((orig_img->data[idx] >> 16) & 0xFF); // extract each R,G,B in the region
green_avg += ((orig_img->data[idx] >> 8) & 0xFF); // and sum them
blue_avg += (orig_img->data[idx] & 0xFF);
}
}
/* Divide the total sum by the amount of pixels in the window */
red_avg /= (N * N - out_of_bounds); // produce an average R,G,B within the region
green_avg /= (N * N - out_of_bounds);
blue_avg /= (N * N - out_of_bounds);
/* Set the average to the current pixel */
curr_idx = j + i * img->sizeX; // locate index in destination array
pixel = (red_avg << 16) + (green_avg << 8) + blue_avg; // merge the components
img->data[curr_idx] = pixel; // set its value to the average of the region
}
}
}
for (i = 0; i < img->sizeY; i++) {
for (j = 0; j < img->sizeX; j++) {`
Вечный пиксель в сетке...
for (n = i - radius; n <= i + radius; n++) {
for (m = j - radius; m <= j + radius; m++) {
Посетите места в пределах radius
нашего пикселя...
if (n < 0 || m < 0 || n >= img->sizeY || m >= img->sizeX) {
out_of_bounds++;
continue;
(и помните, сколько мы нашли)
idx = m + n * img->sizeX;
Когда мы находим место, мы
n
пикселей вверх (основной пиксель-Y +/- радиус),m
пикселей по ширине (основной пиксель-X +/- радиус),
так...
n
ряды размером X пикселей,
m
для этой строки, это...idx
: пиксельный индекс нашего местоположения
red_avg += ((orig_img->data[idx] >> 16) & 0xFF);
green_avg += ((orig_img->data[idx] >> 8) & 0xFF);
blue_avg += (orig_img->data[idx] & 0xFF);
Подсчитайте данные RGB исходного изображения из каждого места, которое мы посещаем.
/* Divide the total sum by the amount of pixels in the window */
red_avg /= (N * N - out_of_bounds);
green_avg /= (N * N - out_of_bounds);
blue_avg /= (N * N - out_of_bounds);
/* Set the average to the current pixel */
...усреднить все местоположения в пределах radius
каждого основного пикселя...
curr_idx = j + i * img->sizeX;
pixel = (red_avg << 16) + (green_avg << 8) + blue_avg;
img->data[curr_idx] = pixel;
... и установите индекс основного пикселя в выходном файле на среднее значение.