【问题标题】:Unable to increase the region of interest of an image无法增加图像的感兴趣区域
【发布时间】:2019-10-24 01:07:27
【问题描述】:

我正在尝试使用以下算法增加图像的感兴趣区域。

首先,确定 ROI 外部边界的像素集,即 ROI 外部且与内部像素相邻(使用四邻域)的像素。然后,将这个集合的每个像素值替换为 ROI 内其邻居的平均值(这次使用八邻域)。最后,通过包含这组更改的像素来扩展 ROI。这个过程是重复的,可以看作是人为地增加了投资回报率。

伪代码如下-

while there are border pixels:
    border_pixels = []

    # find the border pixels
    for each pixel p=(i, j) in image
        if p is not in ROI and ((i+1, j) in ROI or (i-1, j) in ROI or (i, j+1) in ROI or (i, j-1) in ROI) or (i-1,j-1) in ROI or (i+1,j+1) in ROI):
            add p to border_pixels

    # calculate the averages
    for each pixel p in border_pixels:
        color_sum = 0
        count = 0
        for each pixel n in 8-neighborhood of p:
            if n in ROI:
                color_sum += color(n)
                count += 1
        color(p) = color_sum / count

    # update the ROI
    for each pixel p=(i, j) in border_pixels:
        set p to be in ROI


下面是我的代码

    img = io.imread(path_dir)
    newimg = np.zeros((584, 565,3))
    mask = img == 0
    while(1):
        border_pixels = []
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
               for k in range(0,3):
                if(i+1<=583 and j+1<=564 and i-1>=0 and j-1>=0):
                    if ((mask[i][j][k]) and ((mask[i+1][j][k]== False) or (mask[i-1][j][k]==False) or (mask[i][j+1][k]==False) or (mask[i][j-1][k]==False) or (mask[i-1][j-1][k] == False) or(mask[i+1][j+1][k]==False))):
                        border_pixels.append([i,j,k])

         if len(border_pixels) == 0:
             break

        for (each_i,each_j,each_k) in border_pixels:
            color_sum = 0
            count = 0
            eight_neighbourhood = [[each_i-1,each_j],[each_i+1,each_j],[each_i,each_j-1],[each_i,each_j+1],[each_i-1,each_j-1],[each_i-1,each_j+1],[each_i+1,each_j-1],[each_i+1,each_j+1]]
            for pix_i,pix_j in eight_neighbourhood:
                if (mask[pix_i][pix_j][each_k] == False):
                    color_sum+=img[pix_i,pix_j,each_k]
                    count+=1
            print(color_sum//count)
            img[each_i][each_j][each_k]=(color_sum//count)

        for (i,j,k) in border_pixels:
            mask[i,j,k] = False
            border_pixels.remove([i,j,k])

    io.imsave("tryout6.png",img)

但它没有对图像做任何改变。我得到的图像和以前一样 所以我尝试在第一次迭代时在相同尺寸的黑色图像上绘制边框像素,我得到了以下结果-

我真的不知道我在哪里做错了。

【问题讨论】:

    标签: python image image-processing scikit-image


    【解决方案1】:

    这是一个我认为可以按照您的要求工作的解决方案(尽管我同意@Peter Boone 的观点,即这需要一段时间)。我的实现有一个三重循环,但也许其他人可以让它更快!

    首先,读入图像。使用我的方法,像素值是 0 到 1 之间的浮点数(而不是 0 到 255 之间的整数)。

    import urllib
    import matplotlib.pyplot as plt
    import numpy as np
    from skimage.morphology import  binary_dilation, binary_erosion, disk
    from skimage.color import rgb2gray
    from skimage.filters import threshold_otsu
    
    # create a file-like object from the url
    f = urllib.request.urlopen("https://i.stack.imgur.com/JXxJM.png")
    
    # read the image file in a numpy array
    # note that all pixel values are between 0 and 1 in this image
    a = plt.imread(f)
    

    其次,在边缘添加一些填充,并对图像进行阈值处理。我使用了 Otsu 的方法,但 @Peter Boone 的回答也很有效。

    # add black padding around image 100 px wide
    a = np.pad(a, ((100,100), (100,100), (0,0)), mode = "constant")
    
    # convert to greyscale and perform Otsu's thresholding
    grayscale = rgb2gray(a)
    global_thresh = threshold_otsu(grayscale)
    binary_global1 = grayscale > global_thresh
    
    # define number of pixels to expand the image
    num_px_to_expand = 50
    

    图像,binary_global1 是一个看起来像这样的掩码:

    由于图像是三个通道(RGB),我分别处理通道。我注意到我需要将图像侵蚀大约 5 px,因为图像的外部有一些不寻常的颜色和图案。

    # process each channel (RGB) separately
    for channel in range(a.shape[2]):
    
        # select a single channel
        one_channel = a[:, :, channel]
    
        # reset binary_global for the each channel
        binary_global = binary_global1.copy()
    
        # erode by 5 px to get rid of unusual edges from original image
        binary_global = binary_erosion(binary_global, disk(5))
    
        # turn everything less than the threshold to 0
        one_channel = one_channel * binary_global
    
        # update pixels one at a time
        for jj in range(num_px_to_expand):
    
            # get 1 px ring of to update
            px_to_update = np.logical_xor(binary_dilation(binary_global, disk(1)), 
                                          binary_global)
    
            # update those pixels with the average of their neighborhood
            x, y = np.where(px_to_update == 1)
    
            for x, y in zip(x,y):
                # make 3 x 3 px slices
                slices = np.s_[(x-1):(x+2), (y-1):(y+2)]
    
                # update a single pixel
                one_channel[x, y] = (np.sum(one_channel[slices]*
                                                 binary_global[slices]) / 
                                           np.sum(binary_global[slices]))      
    
    
            # update original image
            a[:,:, channel] = one_channel
    
            # increase binary_global by 1 px dilation
            binary_global = binary_dilation(binary_global, disk(1))
    

    当我绘制输出时,我得到如下内容:

    # plot image
    plt.figure(figsize=[10,10])
    plt.imshow(a)
    

    【讨论】:

    • 谢谢你,很抱歉迟到了,我去别的兔子洞了。
    • 我几乎没有疑问-我真的无法理解最初用5 pixels 侵蚀它背后的想法,我可以看到没有侵蚀和侵蚀的区别,但我无法理解为什么会这样正在发生吗?
    【解决方案2】:

    这是一个有趣的想法。您将需要使用掩码和某种形式的mean ranks 来完成此操作。逐个像素地进行会花费您一段时间,而不是您想要使用不同的卷积过滤器。

    如果你这样做:

    image = io.imread("roi.jpg")
    mask = image[:,:,0] < 30
    just_inside = binary_dilation(mask) ^ mask
    image[~just_inside] = [0,0,0]
    

    您将拥有一个仅代表 ROI 内像素的蒙版。我还将不在该区域的像素设置为 0,0,0。

    然后你就可以得到 roi 之外的像素:

    just_outside = binary_erosion(mask) ^ mask
    

    然后得到每个通道的平均双边:

    mean_blue = mean_bilateral(image[:,:,0], selem=square(3), s0=1, s1=255)
    #etc...
    

    这并不完全正确,但我认为它应该让您朝着正确的方向前进。如果您对图像处理有更多一般性问题,我会查看image.sc。如果您需要更多帮助,请告诉我,因为这是比工作代码更普遍的方向。

    【讨论】:

    • 谢谢你的链接,我一定会去看看的。
    • 你能帮我更多地构建这种方法吗,我有代表外面像素的蒙版,但我无法弄清楚如何进一步接近
    猜你喜欢
    • 2020-01-30
    • 2011-08-10
    • 2012-03-08
    • 1970-01-01
    • 2012-02-22
    • 2017-06-05
    • 2018-06-17
    • 1970-01-01
    相关资源
    最近更新 更多