Image Processing4(Hit or Misss)

Goal

In this tutorial you will learn how to find a given configuration or pattern in a binary image by using the Hit-or-Miss transform (also known as Hit-and-Miss transform). This transform is also the basis of more advanced morphological operations such as thinning or pruning.

在这个教程里,学习利用hit-or-miss变换,寻找二进制图像中给定的模式。hit-or-miss变换也是先进形态学操作的基础。

还是使用cv::morphologyEx这个函数。

Hit-or-Miss theory

In particular, it finds those pixels whose neighbourhood matches the shape of a first structuring element B1 while not matching the shape of a second structuring element B2 at the same time.

在二进制的图像中找到匹配结构元素B1,而不匹配结构元素B2的像素。

Mathematically, the operation applied to an image A can be expressed as follows:

数学表达式如下:

AB=(AB1)(AcB2)

Therefore, the hit-or-miss operation comprises three steps:

  1. Erode image A with structuring element B1.
  2. Erode the complement of image A ( Ac) with structuring element B2.
  3. AND results from step 1 and step 2.

具体步骤如下:

    1.使用结构元素B1腐蚀图像A

    2.使用结构元素B2(一般取B1反)腐蚀图像Ac(图像A的互补)

    3.进行AND操作。

The structuring elements B1 and B2 can be combined into a single element B. Let's see an example:

                                                      hitmiss_kernels.png
Structuring elements (kernels). Left: kernel to 'hit'. Middle: kernel to 'miss'. Right: final combined kernel

左:内核->击中;中间:内核->miss;右:->组合起来的。

In this case, we are looking for a pattern in which the central pixel belongs to the background while the north, south, east, and west pixels belong to the foreground. The rest of pixels in the neighbourhood can be of any kind, we don't care about them. Now, let's apply this kernel to an input image:

在这个例子中,我们寻找一个模式,中间的像素属于背景,而其他邻域像素属于前景。剩余的像素在邻域中,可以啥都是,我们这里并关心他们。现在利用这个内核用于输入的图像。

hitmiss_input.png
输入二进制图像
hitmiss_output.png
输出二进制图像

可以看到只找到了一个位置。

Code

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include "iostream"

using namespace cv;
using namespace std;

int main(){
    Mat input_image = (Mat_<uchar>(8, 8) <<
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 255, 255, 255, 0, 0, 0, 255,
        0, 255, 255, 255, 0, 0, 0, 0,
        0, 255, 255, 255, 0, 255, 0, 0,
        0, 0, 255, 0, 0, 0, 0, 0,
        0, 0, 255, 0, 0, 255, 255, 0,
        0, 255, 0, 255, 0, 0, 255, 0,
        0, 255, 255, 255, 0, 0, 0, 0);

    Mat kernel = (Mat_<int>(3, 3) <<
        0, 1, 0,
        1, -1, 1,
        0, 1, 0);

    Mat output_image;
    morphologyEx(input_image, output_image, MORPH_HITMISS, kernel); //输入,输出,类型,内核

    const int rate = 50;
    kernel = (kernel + 1) * 127;
    kernel.convertTo(kernel, CV_8U); //类型转换,否则kernel无法显示
    
    resize(kernel, kernel, Size(), rate, rate, INTER_NEAREST);
    cout << kernel << endl;
    imshow("kernel", kernel);
    moveWindow("kernel", 0, 0);

    resize(input_image, input_image, Size(), rate, rate, INTER_NEAREST); //输入,输出,大小,X比例因子,Y比例因子,插值类型
    imshow("Original", input_image);
    moveWindow("Original", 0, 200);

    resize(output_image, output_image, Size(), rate, rate, INTER_NEAREST); //输入,输出,大小,X比例因子,Y比例因子,插值类型
    imshow("Hit or Miss", output_image);
    moveWindow("Hit or Miss", 500, 200);

    waitKey(0);
    return 0;
}

由于补充注释已经很清楚了,这里不再解释。

CMakeLists.txt文件如下

cmake_minimum_required(VERSION 2.8)

set(CMAKE_CXX_FLAGS "-std=c++11")
project( DisplayImage )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( DisplayImage main.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )

install(TARGETS DisplayImage RUNTIME DESTINATION bin)

结果如下:


猜你喜欢

转载自blog.csdn.net/qq_27806947/article/details/80277153