侵蚀不正常

时间:2017-04-23 12:36:04

标签: c++ opencv image-processing

我尝试在c ++中实现侵蚀(形态学操作),我使用OpenCV进行读取并显示侵蚀后的第一张图像和图像。

我想逐步解释我的做法:

  1. 我创建了我的"二进制图像" (我只使用了黑色和白色)使用随机值为255或0的矩阵。
  2. 我将初始图片复制到最终图片
  3. 然后我用3x3掩码浏览了矩阵(最终图像),如果我有9的值为255,我会计算。
  4. 我的面具如:

    [255 255 255
    255 255 255
    255 255 255]
    
    1. 如果我的计数器是= 9,我将不同掩模中心的像素着色为黑色。
    2. 这是我的代码:

      #include <iostream>
      #include "opencv2/imgproc/imgproc.hpp"
      #include "opencv2/highgui/highgui.hpp"
      
      using namespace std;
      using namespace cv;
      
      #define WIDTH  16
      #define HEIGHT 16
      
      int main( int argc, char** argv )
      {
          Mat image(HEIGHT, WIDTH, CV_8UC1);
          Mat imageFinal(HEIGHT, WIDTH, CV_8UC1);
      
          int values[WIDTH][HEIGHT] = {0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
                                       0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
                                       0, 0,   0, 255, 255, 255,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
                                       0, 0, 255, 255, 255, 255, 255,   0,   0,   0,   0,   0,   0,   0, 0, 0,
                                       0, 0, 255, 255, 255, 255, 255,   0,   0,   0,   0, 255, 255, 255, 0, 0,
                                       0, 0, 255, 255, 255, 255,   0,   0,   0,   0, 255, 255, 255, 255, 0, 0,
                                       0, 0,   0, 255, 255,   0,   0,   0,   0, 255, 255, 255, 255, 255, 0, 0,
                                       0, 0,   0,   0,   0,   0,   0,   0, 255, 255, 255, 255, 255,   0, 0, 0,
                                       0, 0,   0,   0,   0,   0,   0, 255, 255, 255, 255, 255,   0,   0, 0, 0,
                                       0, 0,   0,   0,   0,   0, 255, 255, 255, 255, 255,   0,   0,   0, 0, 0,
                                       0, 0,   0,   0,   0, 255, 255, 255, 255, 255,   0,   0,   0,   0, 0, 0,
                                       0, 0,   0,   0, 255, 255, 255, 255, 255,   0,   0,   0,   0,   0, 0, 0,
                                       0, 0,   0,   0, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0, 0, 0,
                                       0, 0,   0,   0, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0, 0, 0,
                                       0, 0,   0,   0,   0, 255, 255, 255, 255, 255, 255,   0,   0,   0, 0, 0,
                                       0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0};
      
          for(int row = 0; row < WIDTH; row++){
              for(int col = 0; col < HEIGHT; col++){
                  image.data[col + row * image.cols] = values[row][col];
              }
          }
      
          image.copyTo(imageFinal);
      
          int count = 0;
      
          for(int row = 1; row < image.rows-1; row++){
              for(int col = 1; col < image.cols-1; col++){
                  count = 0;
                  for(int a = -1; a <= 1; a++){
                      for(int b = -1; b <= 1; b++){
                          if(image.at<uchar>(row + a, col + b) == 255){
                              count++;
                          }
                      }
                  }cout << count << endl;
                  if(count == 9){
                      for(int a = -1; a <= 1; a++){
                          for(int b = -1; b <= 1; b++){
                              if(a != 0 && b != 0){
                                  imageFinal.at<uchar>(row + a, col + b) = 0;
                              }
                          }
                      }
                  }
              }
          }
      
          imshow("Image", image);
          imshow("final", imageFinal);
      
          waitKey(0);  
          return 0;
      }
      

      但结果却不正确。

      Initial image and correct result: [错误的结果] [1]

1 个答案:

答案 0 :(得分:1)

我不是百分百肯定,但在阅读wiki entry on erosion后,我认为正确的实施将是这样的:

for each pixel(x,y) in original_image
    count neigbours where original_image == 255
    if count == 9
        new_image(x,y) = 255
    else 
        new_image(x,y) = 0
    end
end

,而你有

for each pixel(x,y) in original_image
    count neigbours where original_image == 255
    if count == 9
        set all neighbours (but not the pixel itself) in new_image to 0
end

基本上侵蚀应该对图像的3x3部分进行...

1 1 1         ? ? ?            0 1 1      ? ? ? 
1 1 1    ->   ? 1 ?      and   1 1 1  ->  ? 0 ? 
1 1 1         ? ? ?            1 1 1      ? ? ? 

但你做了

1 1 1         0 0 0 
1 1 1    ->   0 1 0
1 1 1         0 0 0 

应用滤镜时,您应该只更改正在查看的像素的值,但更改所有邻居,而不是像素本身。

我发现维基文章中的公式不太具启发性,也许这有助于理解:

new_image(x,y) = (3x3Sub(old_image,x,y) == mask) * 255