[SciPy-User] How to do symmetry detection?

josef.pktd at gmail.com josef.pktd at gmail.com
Wed Jan 20 10:59:12 EST 2010


On Wed, Jan 20, 2010 at 10:47 AM,  <josef.pktd at gmail.com> wrote:
> On Wed, Jan 20, 2010 at 10:43 AM,  <josef.pktd at gmail.com> wrote:
>> On Wed, Jan 20, 2010 at 10:20 AM, iCy-fLaME <icy.flame.gm at gmail.com> wrote:
>>> Hello,
>>>
>>> I have some signals in mirror pairs in an 1D/2D array, and I am trying
>>> to identify the symmetry axis.
>>>
>>> A simplified example of the signal pair can look like this:
>>> [0, 0, 0, 0, 2, 3, 4, 0, 0, 0, 4, 3, 2, 0]
>>>
>>> The ideal output in this case will probably be:
>>> [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
>>>
>>> As long as the symmetry point has the largest value, it will be fine.
>>>
>>> There can be multiple pairs of signals in the array, and the length of
>>> separation and duration of the signal can vary from pair to pair. The
>>> overall length of the array is about 1k points. The output array
>>> should reflect the level of likeness between the two sides of the
>>> array.
>>>
>>> I tried doing a loop as follows:
>>>
>>> ############ Begin ############
>>> from numpy import array
>>> from numpy import zeros
>>> from numpy import arange
>>>
>>> data =  array([0,0,0,0,2,3,4,0,0,0,4,3,2,0])
>>> length = len(data)
>>> result = zeros(length)
>>>
>>> left = arange(length)
>>> left[0] = 0                 # Index to be used for the end of the left portion
>>>
>>> right = arange(length) + 1
>>> right[-1] = length - 1      # Index to be used for the begining of the
>>> right hand portion
>>>
>>> for i in range(length):
>>>    l_part = zeros(length)  # Default values to be zero, so
>>> non-overlapping region will
>>>    r_part = zeros(length)  #   return zero after the multiplication.
>>>
>>>    l_part[:left[i]] = data[:left[i]][::-1]     # Take the left hand
>>> side and mirror it
>>>    r_part[:length-right[i]] = data[right[i]:]  # Take the right hand side
>>>    result[i] = sum(l_part*r_part)/length   # Use the product and
>>> integral to find the similarity metric.
>>>
>>>    print l_part
>>>    print r_part
>>>    print "===============================", result[i]
>>>
>>>
>>> print result
>>>
>>>
>>> ############ END ############
>>>
>>>
>>> But it is rather slow for a 1000x1000 2D array, anyone got any
>>> suggestion for a more elegant solution?
>>
>>
>> not as general and flexible but fast
>>
>>>>> a=np.array([0, 0, 0, 0, 2, 3, 4, 0, 0, 0, 4, 3, 2, 0])
>>>>> kw = [-1.,-1,-1,0,1,1,1]
>>
>>>>> (signal.convolve(a,kw,'valid')==0).astype(int)
>> array([0, 0, 0, 0, 0, 1, 0, 0])
>>
>> convolve can handle also nd
>>
>> One idea might be to use something like this in a first round, and use
>> the more correct loop solution only if there are several shorter
>> mirrors found by convolve. Also a guess on the likely length might
>> improve the choice of window.
>> Distance measure is additive not multiplicative.
>
> or maybe this is not a great idea. if you have integers, there might
> be many cancellations and wrong detections.

or maybe not with a window liike

>>> ws=3;kw = (np.pi/3.15)**np.abs(np.arange(-ws,ws+1))*np.sign(np.arange(-ws,ws+1))
>>> kw
array([-0.99201436, -0.99466913, -0.997331  ,  0.        ,  0.997331  ,
        0.99466913,  0.99201436])

Josef



More information about the SciPy-User mailing list