9

Some videos have frames that have black strips like borders. I have to remove them from the frames. I came up with a crude solution:

import sys, cv2, numpy
import Image, scipy

filename = "snap.jpeg"

img = cv2.imread(filename)

def checkEqual(lst):
    return len(set(lst)) <= 1 ## <-- This is the maximum length of the set

def removeColumns(image):
    for col in range(image.shape[1]):
        for ch in range(3):
            try:
                checkEqual(image[:, col, ch].tolist())
            except IndexError:
                continue
            else:
                if checkEqual(image[:, col, ch].tolist()):
                    try:
                        image = numpy.delete(image, col, 1)
                    except IndexError:
                        continue
                    else:
                        pass
    return image

img2 = removeColumns(img)

print img.shape, img2.shape ## (480, 856, 3) (480, 705, 3)

Here I find the columns that have the same elements and all the videos that I have have black borders. But even if I increase the maximum length in the function checkEqual() from 1 to 20 or 40, the whole black strip is not deleted.

This is the original image: enter image description here

This is the image after running the program: enter image description here

Could anyone give suggestion for a better solution to this problem ? Thanks!

4 Answers 4

24

This problem was already solved in this answer.

from PIL import Image, ImageChops

im = Image.open('iI3ZE.jpg')

def trim(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()
    if bbox:
        return im.crop(bbox)


trim(im).show()

I used Pillow instead of PIL:

pip install pillow

Results in:

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

3

using opencv and numpy as in your attempt how about something like this:

im = cv2.imread(filename)
h,w,d = im.shape
#left limit
for i in range(w):
    if np.sum(im[:,i,:]) > 0:
        break
#right limit
for j in xrange(w-1,0,-1):
    if np.sum(im[:,j,:]) > 0:
        break

cropped = im[:,i:j+1,:].copy() # deep copy to get byte-aligned array needed for opencv 

1 Comment

For me this solution worked best removing black border, whereby pixel values are not necessarily exactly zero - by replacing np.sum with np.mean and > 3. Needed a bit of fiddeling, but very good results (unlike with the other solutions). Thanks!!!
1

I think that you will find that the problem goes away if you work from the other side of the image, as you are checking the first column (col[0] - it's black so you delete it and the black col[1] becomes col[0] then you check the col[1] - skipping the new col[0]....

If you start from the max it would work or if you stay on any given col once you have deleted it. Alternatively you can make a list of which to delete, reverse it and then do the deletions.

Comments

0

Why not calculate the frame and use PIL

from PIL import Image

img = Image.open('myImage.jpeg')
box = (50, 50, 100, 100)
area = img.crop(box)

1 Comment

Then what? Where's the save?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.