Выравнивание гистограммы Python (без Numpy и без построения)

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

import cv2
img=cv2.imread(raw_input())
shape=img.shape
row=shape[0]
col=shape[1]

def df(img): #to make a histogram (count distribution frequency)
    values=[]
    occurances=[]
    for i in range (len(img)):
        for j in img[i]:
            values.append(j)
            if j in values:
                count +=3
                occurances.append(count)
    return occurances

def cdf (img): #cumulative distribution frequency
    values2=[]
    for i in values:
        j=0
        i=i+j
        j+1
        values2.append(i)
    return values2

def h(img): #equation for the new value of each pixel
    h=((cdf(img)-1)/((row*col)-1))*255
    return h

newimage=cv2.imwrite('a.png')

Это пример того, что я пытаюсь сделать. введите здесь описание изображения

Заранее спасибо.


person Fat Cat    schedule 21.11.2017    source источник
comment
Есть несколько модификаций, которые вы должны внести в свой код, чтобы заставить его работать. Скоро опубликую ответ.   -  person R. S. Nikhil Krishna    schedule 21.11.2017
comment
Большое спасибо!   -  person Fat Cat    schedule 21.11.2017
comment
Я разместил это. Если у вас есть какие-либо вопросы, дайте мне знать. Если это поможет вам, примите это как ответ :)   -  person R. S. Nikhil Krishna    schedule 21.11.2017
comment
Спасибо вам большое за это! Можно ли вместо этого заменить функцию выравнивания на h=((cdf(img)-1)/((row*col)-1))*255, поскольку я пытаюсь сделать это без импорта модуля numpy. :)   -  person Fat Cat    schedule 21.11.2017


Ответы (2)


Вот решение с некоторыми изменениями. Это дает следующий вывод

Оригинал: оригинал

Уравнено: histequalized

Основные модификации:

  1. Функции df() и cdf() стали проще. Распечатайте их вывод при выполнении, чтобы проверить, соответствует ли он тому, что вы ожидаете от него.
  2. Функция equalize_image() выравнивает изображение путем интерполяции из нормального диапазона пикселей (то есть range(0,256)) в вашу кумулятивную функцию распределения.

Вот код:

import cv2
img = cv2.imread(raw_input('Please enter the name of your image:'),0) #The ',0' makes it read the image as a grayscale image
row, col = img.shape[:2]


def df(img):  # to make a histogram (count distribution frequency)
    values = [0]*256
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            values[img[i,j]]+=1
    return values


def cdf(hist):  # cumulative distribution frequency
    cdf = [0] * len(hist)   #len(hist) is 256
    cdf[0] = hist[0]
    for i in range(1, len(hist)):
        cdf[i]= cdf[i-1]+hist[i]
    # Now we normalize the histogram
    cdf = [ele*255/cdf[-1] for ele in cdf]      # What your function h was doing before
    return cdf

def equalize_image(image):
    my_cdf = cdf(df(img))
    # use linear interpolation of cdf to find new pixel values. Scipy alternative exists
    import numpy as np
    image_equalized = np.interp(image, range(0,256), my_cdf)
    return image_equalized

eq = equalize_image(img)
cv2.imwrite('equalized.png', eq)
person R. S. Nikhil Krishna    schedule 21.11.2017
comment
Спасибо вам большое за это! Можно ли вместо этого заменить функцию выравнивания на h=((cdf(img)-1)/((row*col)-1))*255, поскольку я пытаюсь сделать это без импорта модуля numpy. - person Fat Cat; 21.11.2017
comment
Будет ли scipy делать @I.V.N? Единственное место, где использовался numpy, - это интерполяция. Мы можем легко заменить интерполяцию numpy интерполяцией scipy - person R. S. Nikhil Krishna; 21.11.2017
comment
Можно ли сделать индексацию вместо интерполяции? - person Fat Cat; 22.11.2017

Если вы не в курсе, opencv предоставляет встроенную функцию для выравнивания гистограммы, задокументированную здесь.

Также относительно вашего кода:

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

Я бы сделал что-то вроде этого:

def df(img): #to make a histogram (count distribution frequency)
    values = [0] * 256
    for i in range(len(img)):
        for j in img[i]:
           values[j] += 1
person Mefaso    schedule 21.11.2017
comment
Благодарю вас! Было бы неправильно добавить эти значения в список, чтобы я мог использовать его для получения совокупной частоты распространения? - person Fat Cat; 21.11.2017
comment
Добавление чего-либо в список добавляет его как новый последний элемент в этот список, т. е. если a = [5,2], a.append(6) приводит к a = [5,2,6]. Я не уверен, как вы планируете продолжать это. Кумулятив определяется как сумма всех предыдущих и текущих элементов, быстрый способ суммировать все элементы в позиции n будет sum(a[0:n]). - person Mefaso; 21.11.2017
comment
FWIW, cv2.equalizeHist() предназначен для использования с изображениями в оттенках серого (т. е. одноканальными). Если у вас есть цветное (3-канальное) изображение, нужно еще подумать, см. этот вопрос . - person scrpy; 21.11.2017