Get value from histogram

Roua_Rouatbi: <p>I have a lot of images to threshold. The correct threshold seems to be where the histogram of the image dies out a bit.<br>
<img src="https://discuss.pytorch.org/uploads/default/original/3X/4/2/420845a8b573ee79c12a83a1f78702e4135b8fcf.png" alt="image" data-base62-sha1="9q9eD0rWhp38rZ4jsPRQ5MwKyXJ" width="399" height="261"><br>
Here for example the correct value to get from the histogram would be about 200.<br>
Except that after 200. The values are not exactly zero. So i can’t pick on the last value there is.<br>
This is my code:</p>
<pre><code class="lang-auto">image=io.imread(image_path)

image = NormalizeData(image)
image = 255 * image
image=image.astype(np.uint8)

hist = cv2.calcHist(image, [0], None, [256], [0,256])
np_hist=np.histogram(image.ravel(),256,[0,256])

n, bins, patches=plt.hist(image.ravel(),256,[0,256])
plt.title('Histogram for gray scale image')
plt.show()
</code></pre>
<p>If anyone knows of any learnable threshold method too that would be great!</p>

Andrei_Cristea: <p>The requirement that the histogram “dies out a bit” is somewhat vague, but it sounds like you can just do this the old fashioned way (no deep learning) - just sort your values and pick the value corresponding to whatever percentile cutoff you think makes sense (i.e. 99.5th percentile or whatnot).</p>

Roua_Rouatbi: <p>I wrote this. But it doesn’t always give the correct value. can you please elaborate more on your method? (keep in mind that the values after 200 are not zero)</p>
<pre><code class="lang-auto">np_hist=np.histogram(image.ravel(),256,[0,256])

def find_nearest(array, value):
    array = np.asarray(array)
    idx = (np.abs(array - value)).argmin()
    return array[idx]

def get_threshold(np_hist):
    n=np_hist[0].copy()
    n.sort()
    try:
        h=np_hist[0][::-1].tolist()
        print(h.index(find_nearest(np_hist[0],np.percentile(n,50))))
        index_pos = len(np_hist[0]) - h.index(find_nearest(h,np.percentile(n,50))) - 1
        print(f'Last Index of element "{np.percentile(n,50)}" in the list : ', index_pos)
    except ValueError as e:
        print(f'Element "{np.percentile(n,50)}" not found in the list: ', e)
    return index_pos
</code></pre>

Matias_Vasquez: <p>Maybe you can try to use <code>ReLU</code> as a way to set a threshold.</p>
<pre data-code-wrap="python"><code class="lang-python">a = torch.randn(300, 300, requires_grad=True) + 5
bins = 401

y, x = a.histogram(bins, range=(0, 10))

plt.bar(x=x.detach().numpy()[:-1], height=y.detach().numpy())
plt.show()
</code></pre>
<p><img src="https://discuss.pytorch.org/uploads/default/original/3X/5/7/57490ee2bfe9ea7c46acaceae6e57782a5fa6f8e.png" alt="image" data-base62-sha1="csa46OigIpeKMRVUTe8wH1MT7Do" width="375" height="248"></p>
<pre data-code-wrap="python"><code class="lang-python">class MyNet(torch.nn.Module):
    def __init__(self, threshold=7.):
        super().__init__()
        self.p = torch.nn.Parameter(torch.tensor([threshold]))
        self.relu = torch.nn.ReLU()

    def forward(self, x):
        x = x - self.relu(x-self.p)
        return x

net = MyNet()
b = net(a) # The same a as above

y, x = b.histogram(bins, range=(0, 10))

plt.bar(x=x.detach().numpy()[:-1], height=y.detach().numpy())
plt.show()
</code></pre>
<p><img src="https://discuss.pytorch.org/uploads/default/original/3X/f/4/f41ac22661ce297bedab549b6bd8097f866091ee.png" alt="image" data-base62-sha1="yPrPBIC63SI3sCia27BVDbgC0Ca" width="381" height="248"></p>
<p>But as <a class="mention" href="/u/andrei_cristea">@Andrei_Cristea</a> said, it might make more sense to do this without DL.</p>

Andrei_Cristea: <p>Hi Roua,</p>
<p>I just meant something as simple as this:</p>
<pre><code class="lang-auto">threshold_percentile = 99
threshold_value = np.percentile(image.ravel(), threshold_percentile)
</code></pre>
<p>Where the <code>threshold_percentile</code> is chosen to satisfy you original requirement that</p>
<blockquote>
<p>the image dies out a bit.</p>
</blockquote>
<p>Which to me suggests something in the 90s (like 95 or 99) rather than 50 as you showed in your snippet.</p>
<p>If this doesn’t do what you’d like, perhaps you can show an example of what this yields and what you’d like the it to yield instead.</p>

Roua_Rouatbi: <aside class="quote no-group" data-username="Andrei_Cristea" data-post="6" data-topic="152340">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/andrei_cristea/48/47843_2.png" class="avatar"> Andrei_Cristea:</div>
<blockquote>
<pre><code class="lang-auto">threshold_percentile = 99
threshold_value = np.percentile(image.ravel(), threshold_percentile)
</code></pre>
</blockquote>
</aside>
<p>Yes this might work. I will try it out <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>