Обрезать отсканированные изображения с помощью PIL? - PullRequest
2 голосов
/ 23 сентября 2011

Каков будет подход к обрезке изображения, которое было введено с помощью сканера и поэтому имеет большую белую / черную область?

Ответы [ 2 ]

4 голосов
/ 29 декабря 2011

решение энтропии кажется проблематичным и чрезмерно интенсивным в вычислительном отношении. Почему бы не обнаружить края?

Я только что написал этот код на Python, чтобы решить эту проблему для себя. Мой фон был грязно-белым, поэтому я использовал критерии темноты и цвета. Я упростил этот критерий, просто взяв наименьшее из значений R, B или B для каждого пикселя, чтобы черный или насыщенный красный оба выделялись одинаково. Я также использовал среднее количество самых темных пикселей для каждой строки или столбца. Затем я начал с каждого края и работал, пока не переступил порог.

Вот мой код:

#these values set how sensitive the bounding box detection is
threshold = 200     #the average of the darkest values must be _below_ this to count (0 is darkest, 255 is lightest)
obviousness = 50    #how many of the darkest pixels to include (1 would mean a single dark pixel triggers it)

from PIL import Image

def find_line(vals):
    #implement edge detection once, use many times 
    for i,tmp in enumerate(vals):
        tmp.sort()
        average = float(sum(tmp[:obviousness]))/len(tmp[:obviousness])
        if average <= threshold:
            return i
    return i    #i is left over from failed threshold finding, it is the bounds

def getbox(img):
    #get the bounding box of the interesting part of a PIL image object
    #this is done by getting the darekest of the R, G or B value of each pixel
    #and finding were the edge gest dark/colored enough
    #returns a tuple of (left,upper,right,lower)

    width, height = img.size    #for making a 2d array
    retval = [0,0,width,height] #values will be disposed of, but this is a black image's box 

    pixels = list(img.getdata())
    vals = []                   #store the value of the darkest color
    for pixel in pixels:
        vals.append(min(pixel)) #the darkest of the R,G or B values

    #make 2d array
    vals = np.array([vals[i * width:(i + 1) * width] for i in xrange(height)])

    #start with upper bounds
    forupper = vals.copy()
    retval[1] = find_line(forupper)

    #next, do lower bounds
    forlower = vals.copy()
    forlower = np.flipud(forlower)
    retval[3] = height - find_line(forlower)

    #left edge, same as before but roatate the data so left edge is top edge
    forleft = vals.copy()
    forleft = np.swapaxes(forleft,0,1)
    retval[0] = find_line(forleft)

    #and right edge is bottom edge of rotated array
    forright = vals.copy()
    forright = np.swapaxes(forright,0,1)
    forright = np.flipud(forright)
    retval[2] = width - find_line(forright)

    if retval[0] >= retval[2] or retval[1] >= retval[3]:
        print "error, bounding box is not legit"
        return None
    return tuple(retval)

if __name__ == '__main__':
    image = Image.open('cat.jpg')
    box = getbox(image)
    print "result is: ",box
    result = image.crop(box)
    result.show()
2 голосов
/ 23 сентября 2011

Для начала Вот похожий вопрос . Вот связанный с этим вопрос . И еще один связанный с этим вопрос .

Вот только одна идея, безусловно, существуют другие подходы.Я выбрал бы произвольный край обрезки и затем измерил энтропию * по обе стороны от линии, затем продолжил бы повторно выбирать линию обрезки (вероятно, используя что-то вроде метода деления пополам) до энтропии обрезанногочасть падает ниже определенного порога.Как я думаю, вам, возможно, придется прибегнуть к методу грубого поиска корней, так как у вас не будет четких указаний на то, когда вы подрезали слишком мало.Затем повторите для оставшихся 3 ребер.

* Я вспоминаю, как обнаружил, что метод энтропии на указанном веб-сайте не был полностью точным, но я не смог найти свои заметки (уверен, что это был пост SO,однако.)

Редактировать: Другими критериями "пустоты" части изображения (кроме энтропии) могут быть коэффициент контрастности или коэффициент контрастности для результата обнаружения края.

...