这是一种在 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