Пожалуйста, объясните, как этот код удаляет шум из изображения

#c #image-processing

#c #обработка изображений

Вопрос:

Как приведенный ниже код на самом деле удаляет шум из изображения? Я пытаюсь понять, что происходит, но, похоже, не могу уловить общую идею. Я пробовал это, и это работает (но не очень хорошо). Пожалуйста, дайте приблизительное объяснение. Спасибо.

 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 windown");
    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) amp; 0xFF);
      green_avg  = ((orig_img->data[idx] >> 8) amp; 0xFF);
      blue_avg  = (orig_img->data[idx] amp; 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;
    }
  }
}
  

Ответ №1:

 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 пиксели по горизонтали (main-pixel-X /- radius), так что…

  • n строки размером в пиксели,

  • плюс m для этой строки равен…

idx : индекс пикселя нашего местоположения

  red_avg  = ((orig_img->data[idx] >> 16) amp; 0xFF);
 green_avg  = ((orig_img->data[idx] >> 8) amp; 0xFF);
 blue_avg  = (orig_img->data[idx] amp; 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;
  

…и установите main-pixel-index в выходном файле на среднее значение.

Ответ №2:

Код исследует окрестности каждого пикселя, находит среднее значение каждого компонента 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 windown");
    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) amp; 0xFF);   // extract each R,G,B in the region
      green_avg  = ((orig_img->data[idx] >> 8) amp; 0xFF);  // and sum them
      blue_avg  = (orig_img->data[idx] amp; 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
    }
  }
}