我在 PIL 上工作不多,所以我会尝试使用 OPenCV 来实现该解决方案,如果您满意,那么您可以努力使用 PIL 重写代码。
假设:
- 边框仅出现在给定图像的顶部和底部
框架。
- 边框为深黑色。
让我们来一张样张图片:
首先我们加载给定的图像找到给定图像的长度和宽度。
import cv2
img = cv2.imread("sample_frame.jpg") #Loading an image in RGB mode.
height, width, channels = img.shape
现在我们迭代与高度平行且与两侧相距 (width * 0.5) 的像素,或者您可以说是图像的中心。
我们知道边框是深黑色的,因此根据我们的假设,因此黑色 (R, G, B) = (0, 0, 0)。或者我们可以说所有值都严格小于 4(包括图像中的一些噪声)。
border_threshold_R = 4
border_threshold_G = 4
border_threshold_B = 4
mid_pixels = []
top_border_height = 0
bottom_border_height = 0
在上半部分迭代:
for i in xrange(height/2):
mid_pixel_top_half = img[i][width/2]
R, G, B = mid_pixel_top_half[2], mid_pixel_top_half[1], mid_pixel_top_half[0]
if (R<border_threshold_R) and (G<border_threshold_G) and (B<border_threshold_B):
top_border_height+=1
else:
break
迭代下半部分:
for i in xrange(height-1, (height/2)-1, -1):
mid_pixel_bottom_half = img[i][width/2]
R, G, B = mid_pixel_bottom_half[2], mid_pixel_bottom_half[1], mid_pixel_bottom_half[0]
if (R<border_threshold_R) and (G<border_threshold_G) and (B<border_threshold_B):
bottom_border_height+=1
else:
break
现在我们有了给定图像为深黑色的范围,但我们仍然不能说它是否包含边框。为了解决这个问题,让我们在平行于图像宽度的方向上随机迭代,但距离小于top_border_height 和bottom_border_height,并检查我们是否可以成功地迭代一条 (R, G, B) 像素值小于阈值(
让我们定义一个函数,该函数仅在整行的 RGB 值小于阈值时返回 true。
def iterate_line(img, r_thresh, g_thresh, b_thresh, y):
"""
This function returns true only when a given row at a height "y"
from the origin(top - left) if fully black and false othrwise
"""
for i in img[y]:
if not((i[0]<b_thresh) and (i[1]<g_thresh) and i[2]<b_thresh):
return False
return True
现在迭代假定的边框尺寸以准确找到边框的尺寸。
corrected_top_border_height = 0
corrected_bottom_border_height =0
for i in xrange(top_border_height):
if iterate_line(img, border_threshold_R, border_threshold_G, border_threshold_B, i):
corrected_top_border_height+=1
else:
break
for i in xrange(height-1, height-1-bottom_border_height, -1):
if iterate_line(img, border_threshold_R, border_threshold_G, border_threshold_B, i):
corrected_bottom_border_height+=1
else:
break
对于给定的图像,各自的值是:
top_border_height : 15
bottom_border_height : 15
corrected_top_border_height : 8
corrected_bottom_border_height : 8
完整的代码可能如下所示:
import cv2
img = cv2.imread("sample_frame.jpg") #Loading an image in RGB mode.
def iterate_line(img, r_thresh, g_thresh, b_thresh, y):
"""
This function returns true only when a given row at a height "y"
from the origin(top - left) if fully black and false othrwise
"""
for i in img[y]:
if not((i[0] < r_thresh) and (i[1] < g_thresh) and i[2] < b_thresh):
return False
return True
height, width, channels = img.shape
print width, height
border_threshold_R = 4
border_threshold_G = 4
border_threshold_B = 4
top_border_height = 0
bottom_border_height = 0
for i in xrange(height/2):
mid_pixel_top_half = img[i][width/2]
R, G, B = mid_pixel_top_half[2], mid_pixel_top_half[1], mid_pixel_top_half[0]
if (R<border_threshold_R) and (G<border_threshold_G) and (B<border_threshold_B):
top_border_height+=1
else:
break
for i in xrange(height-1, (height/2)-1, -1):
mid_pixel_bottom_half = img[i][width/2]
R, G, B = mid_pixel_bottom_half[2], mid_pixel_bottom_half[1], mid_pixel_bottom_half[0]
if (R<border_threshold_R) and (G<border_threshold_G) and (B<border_threshold_B):
bottom_border_height+=1
else:
break
if (top_border_height>1) and (bottom_border_height>1):
corrected_top_border_height = 0
corrected_bottom_border_height =0
for i in xrange(top_border_height):
if iterate_line(img, border_threshold_R, border_threshold_G, border_threshold_B, i):
corrected_top_border_height+=1
else:
break
for i in xrange(height-1, height-1-bottom_border_height, -1):
if iterate_line(img, border_threshold_R, border_threshold_G, border_threshold_B, i):
corrected_bottom_border_height+=1
else:
break
if corrected_bottom_border_height>1 and corrected_top_border_height>1:
print "The frame has borders."
else:
print "The frame has no borders."
else:
print "The frame has no borders."
print top_border_height, bottom_border_height
print corrected_top_border_height, corrected_bottom_border_height