7

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!

Animesh Pandey
  • 5,900
  • 13
  • 64
  • 130

4 Answers4

23

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

Dreaded semicolon
  • 2,274
  • 1
  • 28
  • 43
metakermit
  • 21,267
  • 15
  • 86
  • 95
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 
John Greenall
  • 1,670
  • 11
  • 17
  • 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!!! – Wolfgang Jul 08 '19 at 15:30
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.

Steve Barnes
  • 27,618
  • 6
  • 63
  • 73
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)
Kobi K
  • 7,743
  • 6
  • 42
  • 86