在直方图Python中找到两个最高峰的中心值

时间:2017-11-02 22:58:06

标签: python opencv histogram

我正在努力寻找“中间人”。直方图中最高峰和第二高峰之间的值。我当然可以手动执行此操作,但我想创建一个自动方法。要计算我的直方图,我使用:

hist= cv2.calcHist([gray_scale_img], [0], None, [256], [0, 256])

到目前为止,我只想出了如何使用max = np.argmax(hist)计算出最大峰值。我附上了一张图片,红色是我的目标。 HISTOGRAM IMAGE

2 个答案:

答案 0 :(得分:1)

以下是如何计算直方图的前2个峰之间的索引和值(使用OpenCV和Python 3)。

import numpy as np
import cv2

img = cv2.imread('../test.jpg', cv2.IMREAD_GRAYSCALE);

#Compute histogram
hist = cv2.calcHist([img], [0], None, [256], [0, 256])

#Convert histogram to simple list
hist = [val[0] for val in hist]; 

#Generate a list of indices
indices = list(range(0, 256));

#Descending sort-by-key with histogram value as key
s = [(x,y) for y,x in sorted(zip(hist,indices), reverse=True)]

#Index of highest peak in histogram
index_of_highest_peak = s[0][0];

#Index of second highest peak in histogram
index_of_second_highest_peak = s[1][0];


print(index_of_highest_peak)
print(index_of_second_highest_peak)

#If top 2 indices are adjacent to each other, there won't be a midpoint
if abs(index_of_highest_peak - index_of_second_highest_peak) < 2:
    raise Exception('Midpoint does not exist');
else: #Compute mid index
    midpoint = int( (index_of_highest_peak + index_of_second_highest_peak) / 2.0 );



print('Index Between Top 2 Peaks = ', midpoint);
print('Histogram Value At MidPoint = ', hist[midpoint]);

我假设如果前2个峰彼此相邻,则不会有中点。您可以根据自己的需要调整此案例。

答案 1 :(得分:0)

您尝试的内容与Otsu thresholding algorithm非常相似。在这种情况下,您可以使用

ret, otsu = cv2.threshold(gray_scale_img , 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)

如果您的数据非常强调且Otsu的方法不令人满意,那么对应的方法是将kmeans clustering应用于3个群集。 Otsu的方法和kmeans都通过最小化类内方差来对数据进行分类。在代码中:

import numpy as np
from sklearn.cluster import KMeans
# Make trimodal data
# (if image is large, consider downsampling it)
n1 = np.random.normal(80, 10, 200)
n2 = np.random.normal(120, 10, 200)
n3 = np.random.normal(180, 10, 400)
imflat = np.r_[n1, n2, n3]
# shuffle and reshape
np.random.shuffle(imflat)
im = imflat.reshape(-1, 1)
km = KMeans(n_clusters=3, random_state=0).fit(im)
lab = km.labels_
# maxmimum data value in each cluster
[im[np.argwhere(lab==i)].flatten().max() for i in range(3)]

但是,这并不能确定3个簇中哪个簇在直方图中具有最高峰。抱歉不完整的解决方案。另一个建议可能是将6阶多项式拟合到直方图,然后找到转折点。