我正在努力寻找“中间人”。直方图中最高峰和第二高峰之间的值。我当然可以手动执行此操作,但我想创建一个自动方法。要计算我的直方图,我使用:
hist= cv2.calcHist([gray_scale_img], [0], None, [256], [0, 256])
到目前为止,我只想出了如何使用max = np.argmax(hist)
计算出最大峰值。我附上了一张图片,红色是我的目标。
HISTOGRAM IMAGE
答案 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阶多项式拟合到直方图,然后找到转折点。