【问题标题】:Connected Component Labeling Algorithm in PythonPython中的连通分量标记算法
【发布时间】:2018-07-05 12:18:26
【问题描述】:

我的工作需要在图像上应用本地二元运算符。为此,我已经将图像转换为灰色,然后还对图像进行了连接组件分析。

代码如下:

  1. 添加库

     import numpy as np
     import pandas as pd
     import matplotlib.pyplot as plt
     from skimage.io import imread, imshow
     from skimage.color import rgb2gray
     from skimage.morphology import (erosion, dilation, closing, opening,area_closing, area_opening)
     from skimage.measure import label, regionprops, regionprops_table
    
  2. 渲染图像

     plt.figure(figsize=(6,6))
     painting = imread("E:/Project/for_annotation/Gupi Gain0032.jpg")
     plt.imshow(painting);
    
     plt.figure(figsize=(6,6))
    
  3. 二值化图像

     gray_painting = rgb2gray(painting)
     binarized = gray_painting<0.55
     plt.imshow(binarized);
    

4.声明内核

    square = np.array([[1,1,1],
                      [1,1,1],
                      [1,1,1]])
  1. 膨胀函数

     def multi_dil(im, num, element=square):
     for i in range(num):
         im = dilation(im, element)
         return im
    
  2. 侵蚀函数

    def multi_ero(im, num, element=square):
    for i in range(num):
        im = erosion(im, element)
        return im
    
  3. 应用的功能

    plt.figure(figsize=(6,6))
    multi_dilated = multi_dil(binarized, 7)
    area_closed = area_closing(multi_dilated, 50000)
    multi_eroded = multi_ero(area_closed, 7)
    opened = opening(multi_eroded)
    plt.imshow(opened);
    
  4. 标签功能

    plt.figure(figsize=(6,6))
    label_im = label(opened)
    regions = regionprops(label_im)
    plt.imshow(label_im); 
    
  5. 提取特征

    properties = ['area','convex_area','bbox_area', 'extent', 'mean_intensity','solidity', 'eccentricity', 'orientation']
    pd.DataFrame(regionprops_table(label_im, gray_painting, 
    properties=properties))
    
  6. 过滤区域

    masks = []
    bbox = []
    list_of_index = []
    for num, x in enumerate(regions):
        area = x.area
        convex_area = x.convex_area
        if (num!=0 and (area>100) and (convex_area/area <1.05)
        and (convex_area/area >0.95)):
        masks.append(regions[num].convex_image)
        bbox.append(regions[num].bbox)   
        list_of_index.append(num)
     count = len(masks)
    
  7. 提取图像

     fig, ax = plt.subplots(2, int(count/2), figsize=(15,8))
     for axis, box, mask in zip(ax.flatten(), bbox, masks):
         red  =  painting[:,:,0][box[0]:box[2], box[1]:box[3]] * mask
         green = painting[:,:,1][box[0]:box[2], box[1]:box[3]] * mask
         blue  = painting[:,:,2][box[0]:box[2], box[1]:box[3]] * mask
         image = np.dstack([red,green,blue])
         axis.imshow(image)
     plt.tight_layout()
    
     plt.figure(figsize=(6,6))
    
     rgb_mask = np.zeros_like(label_im)
     for x in list_of_index:
         rgb_mask += (label_im==x+1).astype(int)
         red  =  painting[:,:,0] * rgb_mask
         green = painting[:,:,1] * rgb_mask
         blue  = painting[:,:,2] * rgb_mask
         image = np.dstack([red,green,blue])
     plt.imshow(image);
    

我收到一个错误。

ValueError: 列数必须是正整数,而不是 0

【问题讨论】:

  • 如果有人能完成这项对我很有帮助的任务 - 我敢打赌
  • 如果您遇到特定问题,我们可以提供帮助,但没有人会为您完成作业。
  • Img=cv2.imread("C://Users//USER//Pictures//Saved Pictures//fig2.tif",0) [M,N]=Img.shape[: 2] 连接=np.zeros((M,N)) 偏移量=[-1,M,1,-M] 索引=[]
  • for i in range(M): for j in range(N): if(Img(i,j)==1): No_of_Objects=N0_of_Objects+1 Index=[((j-1 )*M + i)] Connected(Index)=Mark while(Index!=0): Img(Index)=0 Neighbors=bsxfun(@plus,Index,Offsets) Neighbors = unique(Neighbors(:)) Index = Neighbors (find(Image(Neighbors))) Connected(Index)=Mark Mark=Mark+Difference
  • 在python中我可以用什么代替@plus?

标签: python algorithm edit connected-components


【解决方案1】:

有一种可能的方法与您尝试的方法相距不远。假设背景像素被分配标签 0,对象像素被分配值 1。

  • 逐行扫描图像;

  • 遇到像素 1 时,设置新标签并执行泛洪填充操作,将 1 替换为新标签。

填水可以很简单的实现:

  • 将起始像素设置为新标签;

  • 递归填充八个邻居,如果他们有一个 1。

https://en.wikipedia.org/wiki/Flood_fill

这个版本的代码很简单。但是您会注意到它很容易溢出堆栈,因为待处理的填充数量可能与图像大小一样大。

def FloodFill(X, Y, Label):
    I[X,Y]= Label
    for all 8-way neighbors (X'=X±1, Y'=Y±1, inside image):
        if I[X',Y'] == 1:
            FloodFill(X', Y', Label)

def CCL(Image I):
    Label= 1
    for Y in range(I.Height):
        for X in range(I.Width):
            if I[X, Y] == 1:
                Label+= 1
                FloodFill(X, Y, Label)

所以我会推荐扫描线版本,它涉及更多一点。

https://en.wikipedia.org/wiki/Flood_fill#Scanline_fill

【讨论】:

    猜你喜欢
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-06
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多