Matthew Tranmer
Matthew Tranmer

Reputation: 425

drawing box around image where there are black pixels in python

I want to draw a box around an image where there are black pixels.

this is my image:(quiz.JPG): enter image description here

and i would like the image to be something like this: enter image description here

but with the code below I get this(quiz2.JPG):

enter image description here

here is what i have tried:

from PIL import Image,ImageDraw

image = Image.open("quiz.JPG").convert('L') #open and convert to black and white

pixels = image.load()
width, height = image.size 
black_pixels= []
for col in range(width):
    for row in range(height):
        pixel = pixels[col, row]
        if pixel == (0): #select pixels that are black
            black_pixels.append((col, row)) #add them to the list of black pixels

def sortCoordinates(lst): #this is just a bubble sort to get the coordinates in order of y values
    length = len(lst) -1
    solved = False

    while not solved:
        solved = True
        for i in range(length):
            if lst[i][1] > lst[i+1][1]:
                solved = False
                lst[i],lst[i+1] = lst[i+1],lst[i]
    return lst

black_pixels = sortCoordinates(black_pixels)

def getShape(black_pixels): # function to generate box from the pixels given
    firstPixelXValue = black_pixels[0][0]
    lastPixelXValue = black_pixels[-1][0]

    tallestPixel = 0
    for pixel in black_pixels:
        YValue = pixel[1]

        if YValue > tallestPixel:
            tallestPixel = YValue
    topMostPixelYValue = tallestPixel


    shortestPixel = pixel[1]
    for pixel in black_pixels:
        YValue = pixel[1]

        if YValue < shortestPixel:
            shortestPixel = YValue
    bottomMostPixelYValue = shortestPixel

    shape = [(firstPixelXValue-4, topMostPixelYValue+2), (lastPixelXValue+4,bottomMostPixelYValue-3)] 
    return shape

questions = {}

count = 0
count2 = 0
currentQuestionPixels = []
oldPixelY = black_pixels[0][1]
for newPixel in black_pixels:
    newPixelY = newPixel[1]
    if newPixelY > oldPixelY + 100 or len(black_pixels)-1 == count2: #run this if new question is found
        questions[str(count)] = getShape(currentQuestionPixels)
        currentQuestionPixels = []
        count += 1
    oldPixelY = newPixelY
    currentQuestionPixels.append(newPixel)
    count2 += 1

image = image.convert('RGB')
for question in questions: #draw shape around all questions found
    shape = questions.get(question)
    img1 = ImageDraw.Draw(image)   
    img1.rectangle(shape, outline ="red") 

image.save("quiz2.JPG") 

This should work, in theory, because I am getting all the black pixel coordinates and sorting them out into their Y values. Then I am looping through the black pixels and if the new pixel Y value is grater than the old pixel Y value + 100 or it is the last pixel it must be a new question. So then I draw a box around all the questions

Upvotes: 2

Views: 807

Answers (1)

joonghyup cha
joonghyup cha

Reputation: 624

I've modified the getShape function Check out the code below

from PIL import Image,ImageDraw

image = Image.open("quiz.JPG").convert('L') #open and convert to black and white

pixels = image.load()
width, height = image.size 
black_pixels= []
for col in range(width):
    for row in range(height):
        pixel = pixels[col, row]
        if pixel == (0): #select pixels that are black
            black_pixels.append((col, row)) #add them to the list of black pixels

def sortCoordinates(lst): #this is just a bubble sort to get the coordinates in order of y values
    length = len(lst) -1
    solved = False

    while not solved:
        solved = True
        for i in range(length):
            if lst[i][1] > lst[i+1][1]:
                solved = False
                lst[i],lst[i+1] = lst[i+1],lst[i]
    return lst

black_pixels = sortCoordinates(black_pixels)

def getShape(black_pixels): # function to generate box from the pixels given
    first_x = 0
    first_y = 0
    last_x = 99999999
    last_y = 99999999

    for x, y in black_pixels:

        if first_x < x :
            first_x = x
        if first_y < y :
            first_y = y
        if last_x > x :
            last_x = x
        if last_y > y :
            last_y = y

    shape = [(first_x-4, first_y+2), (last_x+4,last_y-3)]
    return shape

questions = {}

count = 0
count2 = 0
currentQuestionPixels = []
oldPixelY = black_pixels[0][1]
for newPixel in black_pixels:
    newPixelY = newPixel[1]
    if newPixelY > oldPixelY + 100 or len(black_pixels)-1 == count2: #run this if new question is found
        questions[str(count)] = getShape(currentQuestionPixels)
        currentQuestionPixels = []
        count += 1
    oldPixelY = newPixelY
    currentQuestionPixels.append(newPixel)
    # print(currentQuestionPixels)
    count2 += 1

image = image.convert('RGB')
for question in questions: #draw shape around all questions found

    shape = questions.get(question)
    print(shape)
    img1 = ImageDraw.Draw(image)   
    img1.rectangle(shape, outline ="red") 

image.save("quiz2.JPG") 

Upvotes: 4

Related Questions