【问题标题】:How to cut white spaces above the image如何剪切图像上方的空白
【发布时间】:2020-06-17 17:32:24
【问题描述】:

我有一个神经网络项目,可以处理这样的图像:

如您所见,它的边距顶部有一个空白区域。我的问题是这个空间是否会干扰网络结果,如果是的话,考虑到空白在所有图像中的大小和位置不同,我如何使用 python/openCV 仅剪切空白空间

另一个例子:

(打开图片看清楚空白处)

【问题讨论】:

  • 不用裁剪,可以简单的用背景像素填充缺失的信息吗?切割像素,然后扭曲图像以使其达到网络的预期大小,这会使它们显着倾斜,您的网络可能无法在其上进行训练。另一种方法是将这些图像呈现给您的网络并将它们折叠到您的训练中。因此,我们应该回到问题是这些白色区域是如何生成的?
  • 我很抱歉我的无知,但你可以举例说明如何填充背景?
  • 如果对象远离边框,只需复制边框的像素以填充图像。如果您正在训练图像分类管道,理想情况下它们应该忽略这些边界像素,因为它们不是完全白色的。然而,这并不能回答如何这些白色区域是生成的广泛问题。如果我们能够理解这些是如何生成的,那么就有可能提供一种替代我建议的其他两种方法的方法。请描述白色区域是如何生成的。
  • 我有这些来自大型数据集的图像。我已经有图片了
  • 如果已经提供给您,为什么不直接将这些图像提供给网络?请记住,卷积层只是特征提取器,因此颜色均匀的区域会被忽略。

标签: python image opencv image-processing conv-neural-network


【解决方案1】:

这是在 Python/OpenCV 中用黑色填充空间的一种方法。

用 1 像素宽的白色边框填充图像四周。然后从左上角(0,0)用黑色填充填充图像。然后删除 1 像素宽的边框。这假设您在原始图像的两侧没有任何纯白色的真实数据像素。

输入 1:

import cv2
import numpy as np

# read image
img = cv2.imread('border_image1.jpeg')
#img = cv2.imread('border_image2.jpeg')

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# add 1 pixel white border all around
pad = cv2.copyMakeBorder(gray, 1,1,1,1, cv2.BORDER_CONSTANT, value=255)
h, w = pad.shape

# create zeros mask 2 pixels larger in each dimension
mask = np.zeros([h + 2, w + 2], np.uint8)

# floodfill outer white border with black
img_floodfill = cv2.floodFill(pad, mask, (0,0), 0, (5), (0), flags=8)[1]

# remove border
img_floodfill = img_floodfill[1:h-1, 1:w-1]

# save cropped image
cv2.imwrite('border_image1_floodfilled.png',img_floodfill)
#cv2.imwrite('border_image2_floodfilled.png',img_floodfill)

# show the images
#cv2.imshow("thresh", thresh)
cv2.imshow("pad", pad)
cv2.imshow("img_floodfill", img_floodfill)
cv2.waitKey(0)
cv2.destroyAllWindows()


结果一:


沿对角线边缘剩余的白色区域可能是因为发布的图像是 PNG 图像的 JPG 版本。 JPG 有损压缩会导致这些效果。请注意,我使用了 5 个灰度级较低的差异,以允许该区域中的白色值与纯白色有一些偏差。这减少了多余的白色,但并没有完全去除它。但是,它可能已经改变了图像两侧的一些白色数据像素。所以你可以把它放回 0,但沿对角线区域会剩下更多的白色。



输入 2:

结果 2:

【讨论】:

    【解决方案2】:

    这是一种在 Python/OpenCV 中修剪其所有背景颜色的图像的方法。

    (我并没有尝试优化或精简代码。这只是一个概念的演示。例如,4个平均值的计算可以做成一个函数def,因为它们都是相同的行每一面都重复了代码。如果有人更有效地重写了代码或对其进行了优化,请重新发布,以便其他人受益。

    基本上,对图像进行阈值处理,使背景为黑色,其余为白色作为蒙版。 (我使用 cv2.inRange() 以便可以将彩色图像用于输入。)然后测试掩码的每个外部 1 像素厚边的平均值,看它是否不是纯白色 (255) 以及哪边具有最低的平均值(最暗)。如果不是纯白色和最暗的一面,则增加/减少侧面坐标的值(就像删除该行或列,但实际上并未这样做)。继续从侧面向内测试内部行和列,直到测试的所有行和列都是纯白色。这有点像剥洋葱。然后得到最终的侧坐标并裁剪图像。

    第一张图片:

    import cv2
    import numpy as np
    
    # read image
    img = cv2.imread('border_image1.jpeg')
    #img = cv2.imread('border_image2.jpeg')
    h, w = img.shape[:2]
    
    # threshold so border is black and rest is white (invert as needed)
    lower = (254,254,254)
    upper = (255,255,255)
    mask = cv2.inRange(img, lower, upper)
    mask = 255 - mask
    
    
    # define top and left starting coordinates and starting width and height
    top = 0
    left = 0
    bottom = h
    right = w
    
    # compute the mean of each side of the image and its stop test
    mean_top = np.mean( mask[top:top+1, left:right] )
    mean_left = np.mean( mask[top:bottom, left:left+1] )
    mean_bottom = np.mean( mask[bottom-1:bottom, left:right] )
    mean_right = np.mean( mask[top:bottom, right-1:right] )
    
    mean_minimum = min(mean_top, mean_left, mean_bottom, mean_right)
    
    top_test = "stop" if (mean_top == 255) else "go"
    left_test = "stop" if (mean_left == 255) else "go"
    bottom_test = "stop" if (mean_bottom == 255) else "go"
    right_test = "stop" if (mean_right == 255) else "go"
    #print(top_test,left_test,bottom_test,right_test)
    
    # iterate to compute new side coordinates if mean of given side is not 255 (all white) and it is the current darkest side
    while top_test == "go" or left_test == "go" or right_test == "go" or bottom_test == "go":
    
        # top processing
        if top_test == "go":
            if mean_top != 255:
                if mean_top == mean_minimum:
                    top += 1
                    mean_top = np.mean( mask[top:top+1, left:right] )
                    mean_left = np.mean( mask[top:bottom, left:left+1] )
                    mean_bottom = np.mean( mask[bottom-1:bottom, left:right] )
                    mean_right = np.mean( mask[top:bottom, right-1:right] )
                    mean_minimum = min(mean_top, mean_left, mean_right, mean_bottom)
                    #print("top",mean_top)
                    continue
            else:
                top_test = "stop"   
    
        # left processing
        if left_test == "go":
            if mean_left != 255:
                if mean_left == mean_minimum:
                    left += 1
                    mean_top = np.mean( mask[top:top+1, left:right] )
                    mean_left = np.mean( mask[top:bottom, left:left+1] )
                    mean_bottom = np.mean( mask[bottom-1:bottom, left:right] )
                    mean_right = np.mean( mask[top:bottom, right-1:right] )
                    mean_minimum = min(mean_top, mean_left, mean_right, mean_bottom)
                    #print("left",mean_left)
                    continue
            else:
                left_test = "stop"  
    
        # bottom processing
        if bottom_test == "go":
            if mean_bottom != 255:
                if mean_bottom == mean_minimum:
                    bottom -= 1
                    mean_top = np.mean( mask[top:top+1, left:right] )
                    mean_left = np.mean( mask[top:bottom, left:left+1] )
                    mean_bottom = np.mean( mask[bottom-1:bottom, left:right] )
                    mean_right = np.mean( mask[top:bottom, right-1:right] )
                    mean_minimum = min(mean_top, mean_left, mean_right, mean_bottom)
                    #print("bottom",mean_bottom)
                    continue
            else:
                bottom_test = "stop"    
    
        # right processing
        if right_test == "go":
            if mean_right != 255:
                if mean_right == mean_minimum:
                    right -= 1
                    mean_top = np.mean( mask[top:top+1, left:right] )
                    mean_left = np.mean( mask[top:bottom, left:left+1] )
                    mean_bottom = np.mean( mask[bottom-1:bottom, left:right] )
                    mean_right = np.mean( mask[top:bottom, right-1:right] )
                    mean_minimum = min(mean_top, mean_left, mean_right, mean_bottom)
                    #print("right",mean_right)
                    continue
            else:
                right_test = "stop" 
    
    
    # crop input
    result = img[top:bottom, left:right]
    
    # print crop values 
    print("top: ",top)
    print("bottom: ",bottom)
    print("left: ",left)
    print("right: ",right)
    print("height:",result.shape[0])
    print("width:",result.shape[1])
    
    # save cropped image
    cv2.imwrite('border_image1_cropped.png',result)
    #cv2.imwrite('border_image2_cropped.png',result)
    
    # show the images
    cv2.imshow("mask", mask)
    cv2.imshow("cropped", result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    


    裁剪图像:

    作物坐标:

    top:  132
    bottom:  512
    left:  3
    right:  507
    height: 380
    width: 504
    



    第二张图片:

    裁剪图像:

    作物坐标:

    top:  0
    bottom:  420
    left:  0
    right:  512
    height: 420
    width: 512
    


    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-15
      • 2012-11-09
      • 1970-01-01
      • 2013-12-16
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多