【问题标题】:Detect if image has border using PIL使用 PIL 检测图像是否有边框
【发布时间】:2015-07-30 11:29:51
【问题描述】:

我使用此代码使用 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 肯定也会有边框。

【问题讨论】:

  • 所以基本上对于给定的图像,您想检测它是否有边框?
  • 是的,可以在序列的中间选择图像,例如 i=i/2,以确保您不会在视频的开头使用介绍或黑框(图像是视频中的帧)。我想检测左上角的第一个像素是否为黑色,但这仅适用于黑色边框,我认为它会产生很多误报......
  • 你能附上一张示例图片,让情况更清楚吗?
  • opencv 可能也是此任务的不错选择吗?
  • @Hyperion,使用该帖子的目的是它可以有效地满足您的需求,但是您可能需要对其进行微调。

标签: python border python-imaging-library crop trim


【解决方案1】:

我在 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_heightbottom_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

【讨论】:

  • 我有点急于明天的考试,现在是凌晨 4:04,所以我故意错过/跳过了很多东西,我会在明天之前编辑我的答案,在同时,请随意理解代码并指出您对我的任何假设所需的任何错误或解释。
  • 哇,这太棒了。我已经对其进行了测试,与其他算法相比,我希望得到更长的计算时间,但它仍然很快!加上您的算法检测到this 没有边界,就是这种情况。问题只有两个:它只适用于顶部和底部边框,但视频也可以有一个覆盖所有边的框架,它只适用于黑色,或者至少他需要一个输入颜色才能被检测为边框。唯一的错误是,如果他没有检测到任何边框,他会打印错误,因为未定义“corrected_top_border_height”。
  • 这是我声明很多变量的唯一原因,以便您可以根据自己的选择理解和编辑代码,但是,在给定的测试图像中,边框仅在底部和顶部,所以我基于这些做了假设,该算法很快,因为在任何情况下它都不会迭代整个图像,而是只迭代图像的 5~10%。
  • 能不能加个左右边框检测功能?
猜你喜欢
  • 2021-04-14
  • 2013-03-06
  • 1970-01-01
  • 2016-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
  • 2014-04-02
相关资源
最近更新 更多