Set image analysis curve

I have a bunch of images like this:

enter image description here

Relevant data not available. I need to automatically get about 100 points (regularly x-spaced) on a blue curve. All the curves are very similar, so I need at least 1 pixel accuracy, but a subpixel would be preferable. The good news is that all curves start at 0.0 and end at 1.1, so we can forget about the grid.

Any hints of Python libraries that might help or any other approach? Thanks!

+6
source share
2 answers

I saved your image in file 14154233_input.png . Then this program

 import pylab as plt import numpy as np # Read image from disk and filter all grayscale im = plt.imread("14154233_input.png")[:,:,:3] im -= im.mean(axis=2).reshape(im.shape[0], im.shape[1], 1).repeat(3,axis=2) im_maxnorm = im.max(axis=2) # Find y-position of remaining line ypos = np.ones((im.shape[1])) * np.nan for i in range(im_maxnorm.shape[1]): if im_maxnorm[:,i].max()<0.01: continue ypos[i] = np.argmax(im_maxnorm[:,i]) # Pick only values that are set ys = 1-ypos[np.isfinite(ypos)] # Normalize to 0,1 ys -= ys.min() ys /= ys.max() # Create x values xs = np.linspace(0,1,ys.shape[0]) # Create plot of both # read and filtered image and # data extracted plt.figure(figsize=(4,8)) plt.subplot(211) plt.imshow(im_maxnorm) plt.subplot(212, aspect="equal") plt.plot(xs,ys) plt.show() 

Produces this graph:

Ausgabe

Then you can do whatever you want with xs and ys . Perhaps you should put this code in a function that returns xs and ys or so.

Accuracy can be improved by setting Gaussians on each column or so. If you really need it, tell me.

+6
source

First read the image through

 from scipy.misc import imread im = imread("thefile.png") 

This gives a 3D numpy array, and the third size is the color channels (RGB + alpha). The curve is in the blue channel, but there is also a grid. But in the red channel you have a grid, not a curve. Therefore we use

 a = im[:,:,2] - im[:,:,0] 

Now we need a maximum position along each column. Up to one pixel, it is set

 y0 = np.argmax(a, axis=0) 

The result of this is zero when there is no blue curve in the column, that is, outside the frame. On can get the frame limits on

 xmin, xmax = np.where(y0>0)[0][[0,-1] 

In doing so, you can rescale the x axis.

Then you want subpixel resolution. Let's focus on one column

 f=a[:,x] 

We use one iteration of Newton's method to refine the position of extrema

 y1 = y0 - f'[y]/f''[y] 

Please note that we cannot continue the iteration due to discrete sampling. However, we need a good approximation of the derivatives, so we will use a 5-point scheme for both.

 coefprime = np.array([1,-8, 0, 8, -1], float) coefsec = np.array([-1, 16, -30, 16, -1], float) y1 = y0 - np.dot(f[y0-2:y0+3], coefprime)/np.dot(f[y0-2:y0+3], coefsec) 

PS: Thorsten Kranz was faster than me (at least here), but my answer has subpixel accuracy, and my way of highlighting the blue curve is probably more clear.

+2
source

All Articles