Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I extract this obvious event from this image?

EDIT: I have found a solution :D thanks for the help.

I've created an image processing algorithm which extracts this image from the data. It's complex, so I won't go into detail, but this image is essentially a giant numpy array (it's visualizing angular dependence of pixel intensity of an object).

I want to write a program which automatically determines when the curves switch direction. I have the data and I also have this image, but it turns out doing something meaningful with either has been tricky. Thresholding fails because there are bands of different background color. Sobel operators and Hough Transforms also do not work well for this same reason.

This is really easy for humans to see when this switch happens, but not so easy to tell a computer. Any tips? Thanks!

Tricky!

Edit: Thanks all, I'm now fitting lines to this image after convolution with general gaussian and skeletonization of the result. Any pointers on doing this would be appreciated :)

Skeletonized!

like image 561
Alex Walczak Avatar asked Mar 25 '15 06:03

Alex Walczak


2 Answers

You can take a weighted dot product of successive columns to get a one-dimensional signal that is much easier to work with. You might be able to extract the patterns using this signal:

enter image description here

import numpy as np
A = np.loadtxt("img.txt")
N = A.shape[0]
L = np.logspace(1,2,N)
X = []
for c0,c1 in zip(A.T, A.T[1:]):
    x = c0.dot(c1*L) / (np.linalg.norm(c0)*np.linalg.norm(c1))
    X.append(x)

X = np.array(X)

import pylab as plt

plt.matshow(A,alpha=.5)
plt.plot(X*3-X.mean(),'k',lw=2)
plt.axis('tight')
plt.show()

This is absolutely not a complete answer to the question, but a useful observation that is too long for a comment. I'll delete if a better answer comes along.

like image 57
Hooked Avatar answered Nov 15 '22 09:11

Hooked


With the help of Mark McCurry, I was able to get a good result.

Original

Step 1: Load original image. Remove background by subtracting median of each vertical column from itself.

no_background=[]
for i in range(num_frames):
    no_background.append(orig[:,i]-np.median(orig,1))
no_background=np.array(no_background).T

Subtracted median.

Step 2: Change negative values to 0.

clipped_background = no_background.clip(min=0)

Clipped negative values.

Step 3: Extract a 1D signal. Take weighted sum of the vertical columns, which relates the max intensity in a column to its position.

def exp_func(x):
    return np.dot(np.arange(len(x)), np.power(x, 10))/(np.sum(np.power(x, 10)))

weighted_sum = np.apply_along_axis(exp_func,0, clipped_background)

Signal

Step 4: Take the derivative of 1D signal.

conv = np.convolve([-1.,1],weighted_sum, mode='same')
pl.plot(conv)

1D Derivative

Step 5: Determine when the derivative changes sign.

signs=np.sign(conv)
pl.plot(signs)
pl.ylim(-1.2,1.2)

Convolution

Step 6: Apply median filter to above signal.

filtered_signs=median_filter(signs, 5) #pick window size based on result. second arg and odd number.
pl.plot(filtered_signs)
pl.ylim(-1.2,1.2)

Median Filter

Step 7: Find the indices (frame locations) of when the sign switches. Plot result.

def sign_switch(oneDarray):
    inds=[]
    for ind in range(len(oneDarray)-1):
        if (oneDarray[ind]<0 and oneDarray[ind+1]>0) or (oneDarray[ind]>0 and oneDarray[ind+1]<0):
            inds.append(ind)
    return np.array(inds)

switched_frames = sign_switch(filtered_signs)

Final Result

like image 28
Alex Walczak Avatar answered Nov 15 '22 08:11

Alex Walczak