Fonction d'interpolation bilinéaire lors de la conversion de coordonnées non linéaires avec Python et Numpy

Objectif

Dans la conversion de coordonnées dans le traitement d'image, il est courant d'obtenir les coordonnées de l'image d'origine correspondant à l'indice de (i, j) de l'image convertie en utilisant la conversion inverse et interpoler par un procédé tel que bilinéaire.

En C et C ++ etc., je n'avais pas d'autre choix que de faire pivoter les doubles boucles, mais en Numpy et Python je ne voulais pas utiliser pour les boucles autant que possible, j'ai donc écrit un code qui semble efficace [une page sur Github]( Je l'ai trouvé sur https://github.com/NitishMutha/equirectangular-toolbox/blob/master/nfov.py), alors je l'ai changé pour moi-même.

Inutile de dire que dans le cas de la conversion Affine ou par projection, il est plus rapide d'utiliser la librairie OpenCV dédiée.

Flux de code

1. Trouvez les coordonnées de l'image d'origine référencée par la conversion

Créez un tableau qui enregistre l'indice de coordonnées de (i, j) avant la conversion. Si vous créez un tableau à l'aide d'un tableau et que vous le superposez à l'aide d'une mosaïque ou d'une répétition, vous pouvez le faire en un rien de temps.

Dans l'exemple suivant, il est soustrait du centre de l'image cx, cy, normalisé, puis multiplié par le rapport de circonférence pour le convertir en coordonnées polaires sphériques, mais c'est la même chose.

xline = (np.arange(wid)-cx)*2*pi/wid
yline = -(np.arange(hei)-cy)*pi/hei
Xsline = np.tile(xline,hei)
Ysline = yline.repeat(wid,axis=0)

Il ne vous reste plus qu'à appliquer diverses transformations non linéaires à ces séquences. Des fonctions simples telles que sinus cosinus et logarithme sont préparées dans numpy, donc si vous les passez au tableau telles quelles, elles seront toutes traitées de manière uniforme et c'est beaucoup plus rapide que d'écrire une instruction for.

2. Obtenez l'image convertie en fonction des coordonnées obtenues par interpolation bilinéaire.

Les valeurs de pixels correspondant aux coordonnées obtenues précédemment sont interpolées et finalement remodelées dans la forme de l'image.

Dans le code ci-dessous, si les valeurs maximale et minimale de l'indice de pixel sont dépassées, il est mis en boucle, mais en général, il est préférable de compléter avec une valeur telle que 0.

def _bilinear_interpolation_loop(frame, screen_coord):
    ''' Calculate 
    input: frame and its subpixel coordinate [x,y]
    '''
    frame_height,frame_width,frame_channel =frame.shape
    #uf = np.mod(screen_coord[0],1) * frame_width  # long - width
    #vf = np.mod(screen_coord[1],1) * frame_height  # lat - height

    x0 = np.floor(screen_coord[0]).astype(int)  # coord of pixel to bottom left
    y0 = np.floor(screen_coord[1]).astype(int)
    uf = screen_coord[0]  # long - width
    vf = screen_coord[1]  # lat - height
    x2 = np.add(x0, np.ones(uf.shape).astype(int))  # coords of pixel to top right
    y2 = np.add(y0, np.ones(vf.shape).astype(int))
    
    # Assume Loop 
    x2 = np.where(x2 > frame_width-1, 0, x2)
    y2 = np.where(y2 > frame_height-1, 0, y2)
    
    base_y0 = np.multiply(y0, frame_width)
    base_y2 = np.multiply(y2, frame_width)

    A_idx = np.add(base_y0, x0)
    B_idx = np.add(base_y2, x0)
    C_idx = np.add(base_y0, x2)
    D_idx = np.add(base_y2, x2)

    flat_img = np.reshape(frame, [-1, frame_channel])
    #print(flat_img.shape)
    A = np.take(flat_img, A_idx, axis=0)
    B = np.take(flat_img, B_idx, axis=0)
    C = np.take(flat_img, C_idx, axis=0)
    D = np.take(flat_img, D_idx, axis=0)
    
    wa = np.multiply(x2 - uf, y2 - vf)
    wb = np.multiply(x2 - uf, vf - y0)
    wc = np.multiply(uf - x0, y2 - vf)
    wd = np.multiply(uf - x0, vf - y0)
    #print(wa,wb,wc,wd)
    # interpolate
    AA = np.multiply(A.astype(np.float32), np.array([wa, wa, wa]).T)
    BB = np.multiply(B.astype(np.float32), np.array([wb, wb, wb]).T)
    CC = np.multiply(C.astype(np.float32), np.array([wc, wc, wc]).T)
    DD = np.multiply(D.astype(np.float32), np.array([wd, wd, wd]).T)
    out = np.reshape(np.round(AA + BB + CC + DD).astype(np.uint8), [frame_height, frame_width, 3])
    return out

Exemple d'exécution

Dans le blog suivant, j'ai créé une image lorsque la caméra tout-ciel était virtuellement tournée en fonction de l'image de la projection cylindrique à distance régulière.

https://ossyaritoori.hatenablog.com/entry/2019/12/10/RICOH_THETA_SC%E3%81%A7%E5%A4%9A%E9%87%8D%E9%9C%B2%E5%85%89%E3%83%BB%E5%90%88%E6%88%90%E3%82%92%E3%81%97%E3%81%A6Pixel4%E3%81%BF%E3%81%9F%E3%81%84%E3%81%AB%E3%82%AF%E3%83%AA%E3%82%A2%E3%81%AA

Recommended Posts

Fonction d'interpolation bilinéaire lors de la conversion de coordonnées non linéaires avec Python et Numpy
Environnement et utilisation recommandés lors du développement avec Python
Coordonnées de latitude et de longitude ↔ Conversion de coordonnées UTM avec python
J'ai essayé la synthèse de fonctions et le curry avec python
Résultats lors de l'accélération des calculs numériques avec Python et Numba
[Astuces] Calcul des différences de premier ordre et conversion inverse [python / numpy]
Visualisez la gamme d'insertions internes et externes avec python
Problèmes lors de la création d'un outil de conversion csv-json avec python
Exploration avec Python et Twitter API 1 - Fonction de recherche simple
Astuces Python et Numpy
Associez Python Enum à une fonction pour la rendre appelable
Créons un diagramme PRML avec Python, Numpy et matplotlib.
[python] Remarques lors de la tentative d'utilisation de numpy avec Cython
Programmation avec Python et Tkinter
Chiffrement et déchiffrement avec Python
[Python] Méthode de calcul avec numpy
Implémentation de SMO avec Python + NumPy
Modélisation de fonctions non linéaires en Python
Erreur lors de la lecture avec python
python avec pyenv et venv
Fonctionne avec Python et R
Interpolation automatique des images avec OpenCV et Python (méthode de marche rapide, Navier-Stokes)
Erreur et solution lors de l'installation de python3 avec homebrew sur mac (catalina 10.15)
Exploration avec Python et Twitter API 2-Implémentation de la fonction de recherche d'utilisateurs
[Python] Mémo d'erreur et de solution lors de l'utilisation de venv avec pyenv + anaconda
Comment gérer les erreurs lors de l'installation de Python et de pip avec choco
Résolution avec Ruby, Python et numpy AtCoder ABC054 B Calcul de la matrice
[python3] Implémentez facilement la fonction de sortie du journal de débogage avec journalisation et cliquez sur
"Processus Gauss et apprentissage automatique" Régression de processus Gauss implémentée uniquement avec Python numpy