i want to know how to calculate local minima?
Asked
Active
Viewed 105 times
0
-
just erase the bar. looks like it's always in the same place. -- in general, I'd still recommend morphology operations. -- context: https://stackoverflow.com/questions/70852674/how-do-i-extract-objects-in-image/70853228 – Christoph Rackwitz Jan 26 '22 at 07:59
-
@spyderB what have you tried so far? please see: [MWE](https://stackoverflow.com/help/minimal-reproducible-example) – Bilal Jan 26 '22 at 08:28
-
draw a white rectangle over the bar. done. -- are you asking to to locate the bar? either run an opening/closing operation using an extremely wide kernel, or calculate row sums and threshold in that 1D signal. the bar would be the only object that's _that_ wide. – Christoph Rackwitz Jan 26 '22 at 09:01
-
1Count the black pixels along every vertical. – Yves Daoust Jan 26 '22 at 09:29
-
`np.sum(image, axis=1)` – Christoph Rackwitz Jan 26 '22 at 10:35
2 Answers
2
Let me give it to you in matlab. The code can be easily generalized to python.
% read the image and binarize it
img = imread('https://i.stack.imgur.com/iMKIP.jpg') > 128;
% compute the sum of black pixels, per column
vs = sum(1 - img, 1);
% compute the minimal number of black pixels (ignoring the completely white boundaries)
% this will tell you at which columns you may "cut" the image
thr = min(vs(vs>0));
% find the indices of the columns that do not contain any "object"
sep = find(vs <= the);
% find where objects starts (col indices)
loc = diff(sep) > 1;
% select the column indices at the middle, between objects
col = round(0.5 * (sep(loc(1:end-1)+1) + sep(loc(2:end))));
% visualize the result
imshow(img);
hold on;
plot([col;col], [0*col;size(img,1)*ones(1,numel(col))], 'r', 'LineWidth', 2);
with
col =
130 243 351
Shai
- 102,241
- 35
- 217
- 344
1
import urllib.request
from PIL import Image
from scipy import signal
import numpy as np
from matplotlib import pyplot as plt
urllib.request.urlretrieve(
'https://i.stack.imgur.com/iMKIP.jpg',
"img.png")
img = Image.open("img.png")
img.show()
arr = (np.array(img)<(255)/2) #I'm considering black parts as filled
plt.imshow(arr)
plt.subplot(211)
plt.imshow(arr, aspect="auto")
plt.subplot(212)
plt.plot(arr.sum(axis=0))
plt.xlim(0,arr.shape[1])
Then, in order to find local min:
x_lines = signal.find_peaks(-arr.sum(axis=0))[0]
plt.imshow(arr, aspect="auto")
plt.vlines(x_lines, 0, arr.shape[0], color="r")
Finally if we consider a threshold (for example 50 filled pixel in columns):
threshold = 50
x_lines = signal.find_peaks(-arr.sum(axis=0))[0]
x_lines = x_lines[arr.sum(axis=0)[x_lines]<threshold]
plt.imshow(arr, aspect="auto")
plt.vlines(x_lines, 0, arr.shape[0], color="r")
Edit:
To split picture you need
for i, x in enumerate(x_lines):
if i==0:
plt.imshow(arr[:,:x_lines[i]], cmap="Greys")
plt.savefig("fig%i"%i)
plt.show()
else:
plt.imshow(arr[:,x_lines[i-1]:x_lines[i]], cmap="Greys")
plt.savefig("fig%i"%i)
plt.show()
plt.imshow(arr[:,x_lines[i]:], cmap="Greys")
plt.savefig("fig%i"%(i+1))
plt.show()
Salvatore Daniele Bianco
- 1,225
- 4
- 16
-
since the number of pixels in the "empty" columns is fixed, you don't need to bother with `find_peaks` a simple thresholding will do. – Shai Jan 26 '22 at 15:04
-
@Shai you are right, but I think that without `find_peaks` you will obtain multiple lines between the filled shapes – Salvatore Daniele Bianco Jan 26 '22 at 16:33
-