Image processing - segmenting Huabiao pattern from the picture (including python code)

Image data:

Link: https://pan.baidu.com/s/1-5T0c3ev-l2jvz9ZfjybrQ
Extraction code: qzgo 

 

Article directory

foreword

1. Grabcut algorithm

1. The principle of the Grabcut algorithm

2. Implementation steps of GrabCut algorithm

3. Code implementation and operation method

2. Region growing algorithm

1. The principle of the region growing algorithm

2. Implementation steps of the region growing algorithm

3. Code implementation

 Summarize


foreword

In this paper, the region growing algorithm and the Grabcut algorithm are used to segment the image respectively. Two methods were developed.

Original image (beijing.jpg):

 

Grabcut algorithm segmentation effect:

 

Region growing algorithm segmentation effect:

 


1. Grabcut algorithm

1. The principle of the Grabcut algorithm

Grabcut is an interactive image segmentation technology using graph cut image segmentation and maximum flow technology . It requires the user to input a bounding box as the segmentation target position to realize the separation/segmentation of the target and the background. Grabcut mainly includes k-means clustering , Gaussian mixture model modeling (GMM), knowledge of max flow/min cut part. 

 

2. Implementation steps of GrabCut algorithm

(1) Define (one or more) rectangles containing objects in the picture (for the convenience of realization, I use the mouse to draw border graphics in this question).

(2) The area outside the rectangle is automatically considered as the background.

(3) For the user-defined rectangular area, the data in the background can be used to distinguish the foreground and background areas inside it.

(4) Use Gaussian Mixture Model (GMM) to model background and foreground, and mark undefined pixels as possible foreground or background.

(5) Each pixel in the image is considered to be connected to the surrounding pixels through a virtual edge, and each edge has a probability of belonging to the foreground or background, which is based on the similarity in color between it and the surrounding pixels.

(6) Each pixel (that is, a node in the algorithm) will be connected to a foreground or background node.

(7) After the nodes are connected (possibly connected to the background or the foreground), if the edges between the nodes belong to different terminals (that is, one node belongs to the foreground, and the other node belongs to the background), the edges between them will be cut off. The parts of the image can be segmented.

3. Code implementation and operation method

Operation method:

After running the code below, first hold down the left mouse button (a red line will be left) and draw half along the Huabiao pattern, and then use the right mouse button (a blue line will be left) to compare the real-time effect in the pop-up window (the window is called result), Make a supplement (where there is a non-black area, draw a blue line along the corresponding boundary).

The operation scenario is as follows:

 

 final effect:

 

 

#应用Grabcut算法分割图像
import cv2
import numpy as np
import time

drawing = False
mode = False

class GrabCut:
    def __init__(self, t_img):
        self.img = t_img
        self.img_raw = img.copy()
        self.img_width = img.shape[0]
        self.img_height = img.shape[1]
        self.scale_size = 640 * self.img_width // self.img_height
        if self.img_width > 640:
            self.img = cv2.resize(self.img, (640, self.scale_size), interpolation=cv2.INTER_AREA)
        self.img_show = self.img.copy()
        self.img_gc = self.img.copy()
        self.img_gc = cv2.GaussianBlur(self.img_gc, (3, 3), 0)
        self.lb_up = False
        self.rb_up = False
        self.lb_down = False
        self.rb_down = False
        self.mask = np.full(self.img.shape[:2], 2, dtype=np.uint8)
        self.firt_choose = True


# 鼠标的回调函数
def mouse_event2(event, x, y, flags, param):
    global drawing, last_point, start_point
    # 左键按下:开始画图
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        last_point = (x, y)
        start_point = last_point
        param.lb_down = True
        print('mouse lb down')
    elif event == cv2.EVENT_RBUTTONDOWN:
        drawing = True
        last_point = (x, y)
        start_point = last_point
        param.rb_down = True
        print('mouse rb down')
# 按住鼠标移动进行绘制
    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing:
            if param.lb_down:
                cv2.line(param.img_show, last_point, (x,y), (0, 0, 255), 2, -1)
                cv2.rectangle(param.mask, last_point, (x, y), 1, -1, 4)
            else:
                cv2.line(param.img_show, last_point, (x, y), (255, 0, 0), 2, -1)
                cv2.rectangle(param.mask, last_point, (x, y), 0, -1, 4)
            last_point = (x, y)
# 左键释放:结束画图
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        param.lb_up = True
        param.lb_down = False
        cv2.line(param.img_show, last_point, (x,y), (0, 0, 255), 2, -1)
        if param.firt_choose:
            param.firt_choose = False
        cv2.rectangle(param.mask, last_point, (x,y), 1, -1, 4)
        print('mouse lb up')
    elif event == cv2.EVENT_RBUTTONUP:
        drawing = False
        param.rb_up = True
        param.rb_down = False
        cv2.line(param.img_show, last_point, (x,y), (255, 0, 0), 2, -1)
        if param.firt_choose:
            param.firt_choose = False
            param.mask = np.full(param.img.shape[:2], 3, dtype=np.uint8)
        cv2.rectangle(param.mask, last_point, (x,y), 0, -1, 4)
        print('mouse rb up')

        
img_src = 'beijing.jpg'
if __name__ == '__main__':
    img = cv2.imread(img_src)
    if img is None:
        print('error: 图像为空')
    g_img = GrabCut(img)

    cv2.namedWindow('image')
# 定义鼠标的回调函数
    cv2.setMouseCallback('image', mouse_event2, g_img)
    while (True):
        cv2.imshow('image', g_img.img_show)
        if g_img.lb_up or g_img.rb_up:
            g_img.lb_up = False
            g_img.rb_up = False
            start = time.process_time()
            bgdModel = np.zeros((1, 65), np.float64)
            fgdModel = np.zeros((1, 65), np.float64)

            rect = (1, 1, g_img.img.shape[1], g_img.img.shape[0])
            print(g_img.mask)
            mask = g_img.mask
            g_img.img_gc = g_img.img.copy()
            cv2.grabCut(g_img.img_gc, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_MASK)
            elapsed = (time.process_time() - start)
            mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')  # 0和2做背景
            g_img.img_gc = g_img.img_gc * mask2[:, :, np.newaxis]  # 使用蒙板来获取前景区域
            cv2.imshow('result', g_img.img_gc)

            print("Time used:", elapsed)

        if cv2.waitKey(20) == 27:
            break
        #按ESC键退出image

 

2. Region growing algorithm

1.  The principle of the region growing algorithm

Region growing is a kind of image segmentation technique. The basic idea of ​​region growing is to gather similar pixels together to form a region. Region growing starts from one or some pixel points, and finally obtains the whole region, and then realizes the extraction of the target.

2.  Implementation steps of the region growing algorithm

(1) First find a seed pixel for each region that needs to be segmented as the starting point of growth.

(2) Merge the pixels with the same or similar properties as the seed in the neighborhood around the seed pixel (determined according to the predetermined growth or similarity criterion) into the area where the seed pixel is located. And new pixels continue to grow around as seeds, until no more pixels that meet the conditions can be included, and a region is grown.

In this experiment, I use manual selection to select seeds; the judgment criterion of the grayscale image is represented by the grayscale difference being less than a certain threshold.

3. Code implementation

import numpy as np
import matplotlib.pyplot as plt
from skimage import data,io,color
from scipy import ndimage
from skimage import filters
from scipy import signal
class Point(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def getX(self):
        return self.x
    def getY(self):
        return self.y

def getGrayDiff(img,currentPoint,tmpPoint):
    return abs(int(img[currentPoint.x,currentPoint.y]) - int(img[tmpPoint.x,tmpPoint.y]))

def selectConnects(p):
    if p != 0:#八连通
        connects = [Point(-1, -1), Point(0, -1), Point(1, -1), Point(1, 0), Point(1, 1), \
                    Point(0, 1), Point(-1, 1), Point(-1, 0)]
    else:#四联通
        connects = [ Point(0, -1),  Point(1, 0),Point(0, 1), Point(-1, 0)]
    return connects

def regionGrow(img,seeds,thresh,p = 1):
    height, weight = img.shape
    seedMark = np.zeros(img.shape)
    seedList = []
    for seed in seeds:
        seedList.append(seed)
    label = 1
    connects = selectConnects(p)
    while(len(seedList)>0):
        currentPoint = seedList.pop(0)#栈

        seedMark[currentPoint.x,currentPoint.y] = label
        for i in range(len(connects)):
            tmpX = currentPoint.x + connects[i].x
            tmpY = currentPoint.y + connects[i].y
            if tmpX < 0 or tmpY < 0 or tmpX >= height or tmpY >= weight:
                continue
            grayDiff = getGrayDiff(img,currentPoint,Point(tmpX,tmpY))
            if grayDiff < thresh and seedMark[tmpX,tmpY] == 0:
                seedMark[tmpX,tmpY] = label
                seedList.append(Point(tmpX,tmpY))
    return seedMark

img = (color.rgb2grey(io.imread(r'beijing.jpg'))*255).astype(np.int32)
#用中值滤波进行去噪
new_img=ndimage.median_filter(img,3)
#选取种子点
seeds = [Point(10,10),Point(82,150),Point(100,200),Point(20,300)]
binaryImg = regionGrow(new_img,seeds,4)
plt.imshow((1-binaryImg)*new_img,plt.cm.gray)
plt.show()

Renderings:


 Summarize

        In general, the Grabcut algorithm is still much more effective than the region growing algorithm. Not only the pattern is colored, but also the cutting range can be manually delimited, and the image segmentation effect is better, but the segmentation of the Grabcut algorithm requires certain operation techniques. , the region growing algorithm can run the code directly .

Guess you like

Origin blog.csdn.net/weixin_50706330/article/details/127388678