无法增加图像的感兴趣区域

Unable to increase the region of interest of an image

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

First, the set of pixels of the exterior border of the ROI is de termined, i.e., pixels that are outside the ROI and are neighbors (using four-neighborhood) to pixels inside it. Then, each pixel value of this set is replaced with the mean value of its neighbors (this time using eight-neighborhood) inside the ROI. Finally, the ROI is expanded by inclusion of this altered set of pixels. This process is repeated and can be seen as artificially increasing the 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)

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

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

这是一个有趣的想法。您将需要使用掩码和某种形式的 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。如果您需要更多帮助,请告诉我,因为这是比工作代码更通用的方向。

这是一个我认为可以按照您的要求工作的解决方案(尽管我同意@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)