Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 直方图均衡化:未获得所需的输出图像_Python_Opencv_Image Processing - Fatal编程技术网

Python 直方图均衡化:未获得所需的输出图像

Python 直方图均衡化:未获得所需的输出图像,python,opencv,image-processing,Python,Opencv,Image Processing,我试图实现直方图均衡功能自己,但没有得到所需的输出图像 import numpy as np import cv2 import matplotlib.pyplot as plt import math %matplotlib inline def freq(lst): d = {} for i in lst: for j in i: if d.get(j): d[j] += 1 e

我试图实现直方图均衡功能自己,但没有得到所需的输出图像

import numpy as np
import cv2
import matplotlib.pyplot as plt
import math
%matplotlib inline

def freq(lst):
    d = {}
    for i in lst:
        for j in i:
            if d.get(j):
                d[j] += 1
            else:
                d[j] = 1

    return d
def probability(d,total_pixels):
    l = {}
    for i in range(256):
        value = d.get(i)
        if value != None:
            l[i] = value/total_pixels
    return l
def equalizer(d, l):
    f_dic = {}
    last_sum = 0
    for i in range(l):
        if d.get(i):
            prob = d.get(i)
            last_sum = last_sum+((l-1)*prob)
            f_dic[i] = math.floor(last_sum)
    return f_dic
def replace_values(f_dic, img):
    print(f_dic)
    for i in range(len(img)):
        for j in range(len(img)):
            vv = f_dic.get(img[i][j])
            if vv != None:
                img[i][j] = vv
    return img
def histogramEqualization(img):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    freqq = freq(img)
    area = img.shape
    total_pixels = area[0]*area[1]
    prob = probability(freqq, total_pixels)
    f_dic = equalizer(prob,len(img))
    new_img = replace_values(f_dic,img)
    return new_img
pollen_dark = cv2.imread("/home/ahmed/Downloads/dip/DIP_A1_Fall2019/pollen_dark.tif")
new = histogramEqualization(pollen_dark)
plt.imshow(new, cmap='gray')
我得到了这个图像:

输入图像如下:

所需的输出图像是: . 解决这一问题的公式实现


使用NumPy执行此操作的一种方法是使用
np.unique()
查找要修改的值,以及它们的概率分布函数(pdf),基本上是直方图。这可用于根据从pdf上的
np.cumsum()
获得的累积分布函数(cdf),使用以下公式生成相应的规范化值:

round((cdf-min\u cdf)/(num\u体素-min\u cdf)*(depth-1))

整个想法(以及公式)在中以图形的方式进行了很好的描述

这通常是一种比在阵列中循环更干净的方法:

DEPTH = 2 ** 8


def hist_equalization(arr, depth=DEPTH):
    vals, pdf = np.unique(arr, return_counts=True)
    cdf = np.cumsum(pdf)
    min_cdf = min(cdf)
    new_vals = (
        np.round((cdf - min_cdf) / (arr.size - min_cdf) * (depth - 1))
        .astype(int))
    result = np.empty_like(arr)
    for i, val in enumerate(vals):
        result[np.nonzero(arr == val)] = new_vals[i]
    return result


plt.imshow(arr, cmap='gray', vmin=0, vmax=DEPTH - 1)
plt.imshow(hist_equalization(arr), cmap='gray', vmin=0, vmax=DEPTH - 1)
输入:

输出:

(完整的脚本是可用的。请注意,为了方便I/O,我使用了
PIL
而不是
cv
,但这与问题无关。)


编辑 代码中到处都有一些小故障(有些不太严重,有些更严重),但妨碍您获得正确结果的是
equalizer()
根本错误

如果将您的
均衡器()
版本替换为:

def equalizer(pdf, l, depth=2 ** 8):
    min_cdf = pdf[min(pdf)]
    result = {}
    accumulator = 0
    for k, v in sorted(pdf.items()):
        accumulator += v
        result[k] = int(round((accumulator - min_cdf) / (l - min_cdf) * (depth - 1)))     
    return result
被称为:

f_dic = equalizer(freqq, total_pixels)
那么剩下的代码就可以工作了。 请注意,
probability()
完全没有必要,您确实需要
total_pixels
(或
img.size
),因为应用于N维数组的
len(img)
将为您提供沿第0维的长度,而不是像素总数


(这也包括在内。)

您在某处的计算太多了。将中间值z设置为更大的类型以避免出现这种情况(使用8位整数进行计算是不好的)。@CrisLuengo我同意使用8位整数进行计算是危险的,但这在大多数情况下都使用Python
int
s,并且没有溢出。有趣的结果来自
均衡器()
中的一个错误参数/公式。这很有效。但是我对找出我的代码的错误很感兴趣。你能帮我吗?@Mrcreamio看到编辑,但请注意,上面建议的矢量化版本比修复代码所需的最小编辑要快得多,更干净。非常感谢。:)我用
f_dic=均衡器(prob,len(img))
更改了
f_dic=均衡器(prob,2**8)
,它工作了。请参见上面的编辑。我添加了公式,我正在尝试实施。@Creamio先生,很好,你发现了这个问题。如果能够立即在原始代码中实现您试图实现的数学,这将是非常有帮助的。不过,我看不到立即以矢量化形式编写这个新公式的方法。