如何剪切图像上方的空白

2024-04-27 04:11:48 发布

您现在位置:Python中文网/ 问答频道 /正文

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

如你所见,它在页边空白处。我的问题是,这个空间是否会干扰网络的结果,如果是的话,我怎么能用Python/OpenCV切割空白空间,考虑到空白在所有图像

中都不相同的大小和位置。

另一个例子:

(打开图像以清楚地看到空白)


Tags: 项目图像网络空间神经网络opencv空白例子
1条回答
网友
1楼 · 发布于 2024-04-27 04:11:48

下面是一种在Python/OpenCV中修剪图像所有背景色的方法

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

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

第一张图片:

enter image description here

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()


裁剪图像:

enter image description here

作物坐标:

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



第二张图片:

enter image description here

裁剪图像:

enter image description here

作物坐标:

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


网友
2楼 · 发布于 2024-04-27 04:11:48

这里有一种在Python/OpenCV中用黑色填充空格的方法

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

投入1:

enter image description here

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()


结果1:

enter image description here


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



投入2:

enter image description here

结果2:

enter image description here

相关问题 更多 >