2015-10-18 18 views
2

Я слышал о mahotas после this учебник в надежде найти хорошую реализацию полиномов Цернике в питоне. Это не могло быть проще. Тем не менее, мне нужно сравнить евклидову разницу между исходным изображением и реконструированной с момента Зернике. I asked автор mahotas, если бы он мог добавить функциональность реконструкции в свою библиотеку, но у него нет времени на его создание.Реконструкция изображения, основанная на моментах Цернике с использованием mahotas и opencv

Как восстановить изображение в OpenCV с помощью моментов Zernike, предоставленных mahotas?

ответ

5

Исходя из code, упомянутого в его ответе, я разработал следующий код для реконструкции. Я также нашел, что исследования [A. Khotanzad and Y. H. Hong, “Invariant image recognition by Zernike moments”] и [S.-K. Hwang and W.-Y. Kim, “A novel approach to the fast computation of Zernike moments”] очень полезны.

Функция _slow_zernike_poly Конструкция 2-мерных базисных функций Цернике. В функции zernike_reconstruct мы проецируем изображение на базовые функции, возвращаемые _slow_zernike_poly и вычисляем моменты. Затем мы используем формулу восстановления.

Ниже приведен пример реконструкции сделано с помощью этого кода:

входного изображения

input

input-jet

Действительная часть восстановленного изображения с использованием порядка 12

reconstruct-order-12

''' 
Copyright (c) 2015 
Dhanushka Dangampola <[email protected]> 

Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal 
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is 
furnished to do so, subject to the following conditions: 

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software. 

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
THE SOFTWARE. 
''' 

import numpy as np 
from math import atan2 
from numpy import cos, sin, conjugate, sqrt 

def _slow_zernike_poly(Y,X,n,l): 
    def _polar(r,theta): 
     x = r * cos(theta) 
     y = r * sin(theta) 
     return 1.*x+1.j*y 

    def _factorial(n): 
     if n == 0: return 1. 
     return n * _factorial(n - 1) 
    y,x = Y[0],X[0] 
    vxy = np.zeros(Y.size, dtype=complex) 
    index = 0 
    for x,y in zip(X,Y): 
     Vnl = 0. 
     for m in range(int((n-l)//2) + 1): 
      Vnl += (-1.)**m * _factorial(n-m)/\ 
       (_factorial(m) * _factorial((n - 2*m + l) // 2) * _factorial((n - 2*m - l) // 2)) * \ 
       (sqrt(x*x + y*y)**(n - 2*m) * _polar(1.0, l*atan2(y,x))) 
     vxy[index] = Vnl 
     index = index + 1 

    return vxy 

def zernike_reconstruct(img, radius, D, cof): 

    idx = np.ones(img.shape) 

    cofy,cofx = cof 
    cofy = float(cofy) 
    cofx = float(cofx) 
    radius = float(radius)  

    Y,X = np.where(idx > 0) 
    P = img[Y,X].ravel() 
    Yn = ((Y -cofy)/radius).ravel() 
    Xn = ((X -cofx)/radius).ravel() 

    k = (np.sqrt(Xn**2 + Yn**2) <= 1.) 
    frac_center = np.array(P[k], np.double) 
    Yn = Yn[k] 
    Xn = Xn[k] 
    frac_center = frac_center.ravel() 

    # in the discrete case, the normalization factor is not pi but the number of pixels within the unit disk 
    npix = float(frac_center.size) 

    reconstr = np.zeros(img.size, dtype=complex) 
    accum = np.zeros(Yn.size, dtype=complex) 

    for n in range(D+1): 
     for l in range(n+1): 
      if (n-l)%2 == 0: 
       # get the zernike polynomial 
       vxy = _slow_zernike_poly(Yn, Xn, float(n), float(l)) 
       # project the image onto the polynomial and calculate the moment 
       a = sum(frac_center * conjugate(vxy)) * (n + 1)/npix 
       # reconstruct 
       accum += a * vxy 
    reconstr[k] = accum 
    return reconstr 

if __name__ == '__main__': 

    import cv2 
    import pylab as pl 
    from matplotlib import cm 

    D = 12 

    img = cv2.imread('fl.bmp', 0) 

    rows, cols = img.shape 
    radius = cols//2 if rows > cols else rows//2 

    reconst = zernike_reconstruct(img, radius, D, (rows/2., cols/2.)) 

    reconst = reconst.reshape(img.shape) 

    pl.figure(1) 
    pl.imshow(img, cmap=cm.jet, origin = 'upper') 
    pl.figure(2)  
    pl.imshow(reconst.real, cmap=cm.jet, origin = 'upper') 
+0

автор mahotas здесь: рассмотрите вопрос о том, как отправить очищенную версию этого кода в пакет? Или явно лицензировать его как MIT, чтобы он мог быть интегрирован другими? Спасибо – luispedro

+0

@luispedro Я лицензировал его как MIT. Пожалуйста, проверьте его и сообщите мне, если что-то нужно изменить. Честно говоря, я не очень хорошо разбираюсь в лицензировании. – dhanushka

+0

@luispedro Я удалил лицензию MIT из вышеуказанного кода. Я прочитал, что код в SO находится под лицензией Creative Commons, поэтому я не уверен, нарушаю ли я условия SO, лицензируя этот код в MIT. Я думаю, что лучший вариант - отправить версию этого в вашу библиотеку. Пожалуйста посоветуй. – dhanushka

3

Это не так уж сложно, я думаю, вы можете сами его закодировать. Во-первых, помните, что обратное к каждому моменту/матрице aka basic образ является транспонированием этой матрицы, поскольку они ортогональны. Затем просмотрите файл code, который использует эта библиотека для проверки этой функции. Это проще, чем код в библиотеке, чтобы вы могли читать и понимать, как это работает (конечно, гораздо медленнее). Вам нужно получить эти матрицы для каждого момента, которые являются базовыми изображениями. Вы можете изменить _slow_znl, чтобы получить значения для x,y, вычисленные внутри основного цикла for x,y,p in zip(X,Y,P):, и сохранить в матрице того же размера, что и входное изображение. Передайте белое изображение до _slow_zernike и получите все матрицы времени до нужной радиальной степени. Чтобы восстановить изображение с помощью коэффициентов, просто используйте транспонирование этих матриц так же, как вы бы сделали с преобразованием Хаара.

+0

Благодарим вас за это! Я играю с этим кодом, но я ошибаюсь, не могли бы вы указать на мои ошибки? http://pastebin.com/pAqibuqS Я добавил комментарии вокруг того, что я изменил с исходного кода. –

 Смежные вопросы

  • Нет связанных вопросов^_^