Search code examples
pythonimagealgorithmpython-imaging-libraryimage-manipulation

Replace same line of pixels in dynamic images with Pillow in python


I'm trying to work out an algorithm that does the following, input is left image, output is right image:

IMPORTANT: Images are dynamically generated and the horizontal lines I need to remove are always in the same position.

enter image description here

In the output I don't really care about the colors, it could be white, and black like this, although that might be a little more complicated:

enter image description here

So far I've came up with this algorithm for modifying the images:

def modify_image(filename):
    img = Image.open(filename)
    img = img.convert('RGBA')

    pixdata = img.load()

    for y in xrange(img.size[1]):
        for x in xrange(img.size[0]):
            if pixdata[x, y][0] in range(155, 190): #removes horizontal lines but doesn't change them to the vertical lines color
                pixdata[x, y] = (255, 255, 255, 255)
            if pixdata[x, y][0] < 135:
                pixdata[x, y] = (0, 0, 0, 255)

    for y in xrange(img.size[1]):
        for x in xrange(img.size[0]):
            if pixdata[x, y][1] < 195:
                pixdata[x, y] = (0, 0, 0, 255)

    for y in xrange(img.size[1]):
        for x in xrange(img.size[0]):
            if pixdata[x, y][2] > 0:
                pixdata[x, y] = (255, 255, 255, 255)

    img = img.resize((1000, 300), Image.NEAREST)
    im2 = Image.new('P', img.size, 255)
    im = img.convert('P')

    img.save(base_path + "current.jpg")

modify_image (base_path + "image.gif")

This turns the images black and white and sometimes succeeds in isolating the middle bar from the background, the thing is, it doesn't remove the horizontal lines and it doesn't certainly change the color to the one of the vertical line either.

Bear in mind that the colors are merely illustrative and dynamic so think about any possible color.

Any suggestions/approaches are greatly appreciated :)

UPDATE: managed to remove horizontal lines but not replace them with the vertical lines color, so that only partially solves the problem (or not at all)


Solution

  • I don't know how accurate this needs to be but, since the positions of the horizontal bars are fixed, could you copy the pixel values from the row immediately preceding each horizontal bar to each row of the horizontal bar.

    This will not look perfect because of the gradient background, but it might be enough for your purpose. Looking at the first example image, try this:

    import os.path
    from PIL import Image
    
    HORIZONTAL_BAND_1_Y = range(37, 64)
    HORIZONTAL_BAND_2_Y = range(125, 149)
    
    img = Image.open(filename)
    img = img.convert('RGBA')
    pixdata = img.load()
    
    for band in HORIZONTAL_BAND_1_Y, HORIZONTAL_BAND_2_Y:
        for y in band:
            for x in range(img.size[0]):
                pixdata[x,y] = pixdata[x, band[0]-1]
    
    new_filename = os.path.join(os.path.dirname(filename),
                       'new_{}'.format(os.path.basename(filename)))
    
    img.save(new_filename)
    

    Sample ouput

    enter image description here