3

First off, I have read this post. How to detect an image border programmatically? He seems to be asking a slightly different question, on finding the X/Y coordinates though.

I am just trying to find whether or not a solid border exists around a given photo. I've explored using ImageMagick, but is this the best option? I've never done any Image-related programming so I'm hoping there's just a simple api out there that can solve this problem. I'm also fairly new to how to use these libraries, so any advice is appreciated. I'd prefer solutions in Python or Java, anything is fine though.

Thanks!

Community
  • 1
  • 1
Ken
  • 530
  • 4
  • 11
  • 30
  • How different does the border have to be? 1 hue value different, or above some delta? – Phil H Jun 11 '12 at 18:42
  • Do you know anything about the width of the border? – Simeon Visser Jun 11 '12 at 18:58
  • @PhilH I'm not quite sure how to answer that question in those terms sorry - I'd say that it this function should detect any human-detectable border (IE. it's fairly obvious to a human when there is a border around a picture). Also, the pictures I'm dealing with will generally be pictures of houses, landscapes, etc. – Ken Jun 11 '12 at 20:53
  • @SimeonVisser The border widths in the photos I'm working with can and will vary, so I won't know anything about the width of the border ahead of time. – Ken Jun 11 '12 at 20:55

3 Answers3

4

I answered a related question here, that removes any border around an image, it uses PIL. You can easily adapt the code so it returns True or False for whether there is a border or not, like this:

from PIL import Image, ImageChops

def is_there_a_border(im):
    bg = Image.new(im.mode, im.size, im.getpixel((0,0)))
    diff = ImageChops.difference(im, bg)
    diff = ImageChops.add(diff, diff, 2.0, -100)
    bbox = diff.getbbox()
    return bbox != (0,0,im.size[0],im.size[1])

However, this will return True even if only one side of an image has a border. But it sounds like you want to know if there is a border all the way around an image. To do that change the last line to:

    return all((bbox[0], bbox[1], (bbox[0] + bbox[2]) <= im.size[0], 
                                  (bbox[1] + bbox[3]) <= im.size[1]))

This only returns true if there is a border on every side.

For example:

False:

enter image description here

False:

enter image description here

True:

enter image description here

Community
  • 1
  • 1
fraxel
  • 34,470
  • 11
  • 98
  • 102
  • Thanks for your help! That just about works. However, I'm having problems with your solution for finding if there is border all the way around (ie the 'return all' line). I've tried it on pictures with borders and gotten 'False' every time. Do you know why this might be? Could you give me some details on how your answer works? I know that's asking a lot - I'd appreciate it though. Thanks! – Ken Jun 11 '12 at 20:57
  • 1
    @Ken - If you look at [this link](http://stackoverflow.com/questions/10615901/trim-whitespace-using-pil/10616717#10616717),I explain how the main section of the code works. I had a mistake in the final line which I edited around half an hour ago, so make sure you are using the correct code. Maybe you could post a link to an image that it isn't working for, and I'll take a look at it! ;) – fraxel Jun 11 '12 at 21:15
  • Okay great thanks. I did have the correct version of the code. This is the image I'm having problems with: http://imgur.com/qvZHX thanks! – Ken Jun 11 '12 at 22:09
  • 1
    @Ken - fixed, change the `<`s to `<=` :) if you look closely you can see that that image has a one pixel lighter border all the way around. And the equality wasn't handling this edge case correctly. – fraxel Jun 11 '12 at 22:31
  • Great thanks! Your answer was so helpful to me in so many ways. – Ken Jun 12 '12 at 22:12
1

After seeing fraxel's answer, it occurs to me that if you don't care how wide the border is, you could crop out the outermost pixel of each side and check the colour is uniform. Should be very quick; by setting the background color to that of the pixel at 0,0, and cropping 1,1 to w-2,h-2, the remaining image should have exactly 1 colour.

Phil H
  • 19,928
  • 7
  • 68
  • 105
0

so, the correct code of last line should be :

 return all((bbox[0], bbox[1], bbox[2]) < im.size[0], bbox[3] < im.size[1]))

right? for the last two parameters of getbbox() func, are "right, and lower pixel coordinate of the bounding box", not width and height

songofhawk
  • 91
  • 7
  • it just detect whether bbox is smaller than the image in all directions. (bbox[0], bbox[1]) is the upper-left corner of the bounding box, and (bbox[2], bbox[3]) is the lower-right one, if they are all inside the image, there should be a border – songofhawk Aug 14 '19 at 10:37
  • Is it possible to do it with image magical or Java? – plzdontkillme Jan 08 '21 at 12:45