我使用此代码使用PIL删除图像的边框:
def RemoveBlackBorders(img):
bg = Image.new(img.mode, img.size, img.getpixel((0,0)))
diff = ImageChops.difference(img, bg)
diff = ImageChops.add(diff, diff, 2.0, -100)
bbox = diff.getbbox()
if bbox:
return img.crop(bbox)
我在此处找到了:Trim whitespace using PIL
我用它来处理文件夹中包含的所有图像:
def CropImages():
global FOLDER
for i in range(1, len(os.listdir(FOLDER))+1):
image = FOLDER + "\\" + str(i) + ".jpg"
img = Image.open(image)
img = RemoveBlackBorders(img)
img.save(image, "JPEG")
现在问题是这个操作需要花费很多时间才能完成~1000个图像,所以我想要做的是在文件夹中的一个图像有一个要删除的边框的情况下检查开始进程之前,这是因为如果图像1.jpg有边框,那么图像[n] .jpg也可以使用它。
答案 0 :(得分:1)
我还没有在PIL上工作过,所以我会尝试使用OPenCV来实现解决方案,如果你满意的话,你可以付出一些努力来使用PIL重写代码。
做出的假设:
让我们拍一张示例图片:
首先,我们加载给定的图像,找到给定图像的长度和宽度。
import cv2
img = cv2.imread("sample_frame.jpg") #Loading an image in RGB mode.
height, width, channels = img.shape
现在我们迭代平行于高度的像素,并且距离两边的距离(宽度* 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)的线像素值小于阈值(<4)。对于每行成功的迭代,我们增加一个变量,该变量显示边界的校正宽度。
让我们定义一个函数,只有在整行的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