opencv_python實現二值圖像的孔洞填充

 

圖1.左圖:鎳的圖像。中心:閾值和倒置。右:孔填滿

 

在本教程中,我們將學習如何填充二值圖像中的孔。參考圖1左側的圖像,假設我們想要找到一個二值模板,它將硬幣與背景分開,如右圖所示。在本教程中,包含硬幣的圓形區域也將被稱爲前景。

請注意,硬幣的邊界是黑色的,與白色背景不同。因此,我們使用簡單的圖像閾值來將邊界與背景分開。換句話說,我們說強度高於某個值(閾值)的像素是背景,其餘像素是前景。中心圖像顯示此閾值圖像(黑色代表背景,白色代表前景)。不幸的是,即使邊界被很好地提取(它是純白色),硬幣的內部也具有類似於背景的強度。因此,閾值操作不能將其與背景區分開。我們如何用白色填充圓形邊界內的所有像素?

MATLAB有一個名爲imfill的函數 ,允許您填充孔,您可以通過以下方式使用它。

% MATLAB code for filling holes in a binary image. 
im = imfill(im,'holes');

 1、imfill in OpenCV

OpenCV中沒有imfill功能,但我們肯定可以寫一個!這個想法很簡單。我們知道像素(0,0)連接到背景。因此,我們可以通過從像素(0,0)執行填充操作來提取背景。不受洪水填充操作影響的像素必然位於邊界內。反轉並與閾值圖像組合的泛洪圖像就是前景蒙版了!

圖2  在OpenCV中實現imfill的流程

 

2、在OpenCV中實現imfill的步驟

閱讀以下步驟時請參考圖2.

  1. 讀取圖片。

  2. 將輸入圖像二值化。

  3. 從像素(0,0)填充顏色。請注意,步驟2和步驟3的輸出之間的差異在於步驟3中的圖像的背景現在是白色的。

  4. 反轉洪水填充的圖像(即黑色變爲白色,白色變爲黑色)。

  5. 使用按位OR運算將閾值圖像與反向洪水填充圖像組合以獲得填充有孔的最終前景掩模。步驟4中的圖像在邊界內具有一些黑色區域。通過步驟2,填充了圖像中的孔。因此,我們將兩者結合起來得到前景蒙版。

3、用於填充二進制圖像中的孔的C ++和Python代碼

以下是它在代碼
C ++實現:

#include "opencv2/opencv.hpp"
 
using namespace cv;
 
int main(int argc, char **argv)
{
    // Read image
    Mat im_in = imread("nickel.jpg", IMREAD_GRAYSCALE);
 
   
    // Threshold.
    // Set values equal to or above 220 to 0.
    // Set values below 220 to 255.
    Mat im_th;
    threshold(im_in, im_th, 220, 255, THRESH_BINARY_INV);
     
    // Floodfill from point (0, 0)
    Mat im_floodfill = im_th.clone();
    floodFill(im_floodfill, cv::Point(0,0), Scalar(255));
     
    // Invert floodfilled image
    Mat im_floodfill_inv;
    bitwise_not(im_floodfill, im_floodfill_inv);
     
    // Combine the two images to get the foreground.
    Mat im_out = (im_th | im_floodfill_inv);
 
    // Display images
    imshow("Thresholded Image", im_th);
    imshow("Floodfilled Image", im_floodfill);
    imshow("Inverted Floodfilled Image", im_floodfill_inv);
    imshow("Foreground", im_out);
    waitKey(0);
     
}

 Python實現:

import cv2;
import numpy as np;
 
# Read image
im_in = cv2.imread("nickel.jpg", cv2.IMREAD_GRAYSCALE);
 
# Threshold.
# Set values equal to or above 220 to 0.
# Set values below 220 to 255.
 
th, im_th = cv2.threshold(im_in, 220, 255, cv2.THRESH_BINARY_INV);
 
# Copy the thresholded image.
im_floodfill = im_th.copy()
 
# Mask used to flood filling.
# Notice the size needs to be 2 pixels than the image.
h, w = im_th.shape[:2]
mask = np.zeros((h+2, w+2), np.uint8)
 
# Floodfill from point (0, 0)
cv2.floodFill(im_floodfill, mask, (0,0), 255);
 
# Invert floodfilled image
im_floodfill_inv = cv2.bitwise_not(im_floodfill)
 
# Combine the two images to get the foreground.
im_out = im_th | im_floodfill_inv
 
# Display images.
cv2.imshow("Thresholded Image", im_th)
cv2.imshow("Floodfilled Image", im_floodfill)
cv2.imshow("Inverted Floodfilled Image", im_floodfill_inv)
cv2.imshow("Foreground", im_out)
cv2.waitKey(0)

原文地址:https://www.learnopencv.com/filling-holes-in-an-image-using-opencv-python-c/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章