閾値だけが欲しい場合もある。参考はhttps://forum.image.sc/t/understanding-imagej-implementation-of-the-triangle-algorithm-for-threshold/752/10辺り。
多少冗長だが、あとで見返したときのために。
import cv2 import numpy as np def thresh_triangle(hist): start, end = hist.nonzero()[0][[0,-1]] peak = hist.argmax() if peak - start > end - peak: x1, x2 = start, peak y1, y2 = 0, hist[x2] else: x1, x2 = peak, end y1, y2 = hist[x1], 0 # 点(X0, Y0)と直線(X1, Y1) - (X2, Y2)との距離D # A = (Y2 - Y1)*X0 - (X2 - X1)*Y0 + (X2*Y1 - X1*Y2) # B = SQRT((Y2 - Y1)^2 + (X2 - X1)^2) # D = A/B d = [(y2-y1)*i - (x2-x1)*hist[i] for i in range(x1, x2+1)] return np.array(d).argmax() + x1
opencvのもの(THRESH_TRIANGLE)とはちょうど1ずれる。画像はFile:Pavlovsk Railing of bridge Yellow palace Winter.jpg - Wikimedia Commonsから。
img = cv2.imread("800px-Pavlovsk_Railing_of_bridge_Yellow_palace_Winter.jpg", 0) hist = cv2.calcHist([img], [0], None, [256], [0,256]).ravel() th1 = thresh_triangle(hist) th2, _ = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_TRIANGLE) print(th1, th2) # => 218 217.0