[PYTHON] 100 coups sur le traitement d'image !! (021-030) Je veux faire une pause ...

1.Tout d'abord

Pratiquez ceci pour améliorer les capacités techniques du prétraitement d'image 100 coups pour le traitement d'image !! Je vais le faire avec Colaboratory pour qu'il soit facile de démarrer. Nous travaillerons pour atteindre l'objectif dans deux semaines. Je vais l'expliquer soigneusement. Veuillez poser une question! 001 --010 est le lien à droite Traitement d'image Knock 100 !! (001 --010) Soigneusement et soigneusement 011 --020 est le lien à droite 100 coups sur le traitement d'image !! (011 --020) Début du jeu

2. Préparation

Introduit les bibliothèques, etc. comme suit.

python


#Importer la bibliothèque
from google.colab import drive
import numpy as np
import matplotlib.pyplot as plt
import cv2
from google.colab.patches import cv2_imshow

#Chargement des images
img = cv2.imread('Chemin de l'image/imori.jpg')
img_noise = cv2.imread('Chemin de l'image/imori_noise.jpg')
img_dark = cv2.imread('Chemin de l'image/imori_dark.jpg')
img_gamma = cv2.imread('Chemin de l'image/imori_gamma.jpg')
#Image en échelle de gris
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_noise = cv2.cvtColor(img_noise, cv2.COLOR_BGR2GRAY)
gray_dark = cv2.cvtColor(img_dark, cv2.COLOR_BGR2GRAY)
#Pour le stockage d'images
OUT_DIR = 'Chemin de destination de sortie/OUTPUT/'

3. Explication

Q.21. Normalisation de l'histogramme

Mettre en œuvre la normalisation de l'histogramme. On peut voir que l'histogramme a un biais. Par exemple, s'il y a beaucoup de pixels proches de 0, l'image sera globalement sombre, et s'il y a beaucoup de pixels proches de 255, l'image sera lumineuse. Les histogrammes polarisés localement sont exprimés comme ayant une plage dynamique étroite. Par conséquent, afin de rendre l'image plus facile à voir pour l'œil humain, il est nécessaire d'effectuer un traitement tel que la normalisation ou l'aplatissement de l'histogramme. Cette normalisation d'histogramme est appelée transformation en échelle de gris et peut être réalisée par l'équation suivante lors de la conversion d'une image avec une valeur de pixel de [c, d] dans la plage de [a, b]. Cette fois, imori_dark.jpg est converti dans la plage de [0, 255] respectivement. ファイル名

A21


def hist_normalization(img, a=0, b=255):
    """
Normalisation de l'histogramme
    params
    ----------------------------
    param1: numpy.image au format ndarray
    param2:Valeur minimale de la plage d'histogramme
    param3:Valeur maximale de la plage d'histogramme

    returns
    ----------------------------
    numpy.image au format ndarray
    """
	#histogramme(rgb)Valeur maximale / minimale de
    c = img.min()     # 60
    d = img.max()    # 141

    #copie
    out = img.copy()

	#Normalisation
    out = (b - a) / (d - c) * (out - c) + a
    out[out < a] = a
    out[out > b] = b
    out = out.astype(np.uint8)
    return out

#Obtenez la hauteur, la largeur et la couleur de l'image
H, W, C = img_dark.shape

#Normalisation de l'histogramme
out = hist_normalization(img_dark)

#Afficher un histogramme
plt.hist(out.ravel(), bins=255, rwidth=0.8, range=(0, 255))
plt.savefig("img21.png ")
plt.show()
ファイル名 ![img21_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621150/52139d68-fc5d-0658-b887-7badda5ebcc9.png) L'image est également assez nette.

Référence: Hystertic Part 2: Aplatir l'histogramme

Q.22 Fonctionnement de l'histogramme

Faites fonctionner la valeur moyenne de l'histogramme sur m0 = 128 et l'écart type sur s0 = 52. Il s'agit d'une opération qui modifie l'histogramme à plat plutôt que de modifier la plage dynamique de l'histogramme. Pour changer l'histogramme de la valeur moyenne m et de l'écart type s en la valeur moyenne m0 et l'écart type s0, effectuez la conversion par l'équation suivante. ファイル名

A22


def hist_mani(img, m0=128, s0=52):
    """
La valeur moyenne de l'histogramme est m0=128, écart type s0=Exploiter jusqu'à 52 ans

    params
    --------------------------------------
    param1: numpy.image au format ndarray
    param2:Valeur moyenne
    param3:écart-type

    returns
    --------------------------------------
    numpy.image au format ndarray
    """
    #Valeur moyenne
    m = np.mean(img)
    #écart-type
    s = np.std(img)

    #Copie de l'image
    out = img.copy()

    #Calculer selon la formule
    out = s0 / s * (out - m) + m0
    out[out < 0] = 0
    out[out > 255] = 255
    out = out.astype(np.uint8)

    return out

#Manipuler l'histogramme
out = hist_mani(img_dark)

#Sauvegarder le résultat
cv2.imwrite(OUT_DIR + 'ans22_1.jpg', out)
#Afficher l'image
cv2_imshow(out)
cv2.waitKey(0)
cv2.destroyAllWindows()

#Afficher un histogramme
plt.hist(out.ravel(), bins=255, rwidth=0.8, range=(0, 255))
plt.savefig("img22_2.png ")
plt.show()

img22_1.png ファイル名

Référence: Hystertic Part 2: Aplatir l'histogramme

Q.23. Aplatissement de l'histogramme

Mettre en œuvre l'aplatissement de l'histogramme. L'aplatissement de l'histogramme est une opération consistant à changer l'histogramme pour qu'il soit plat, et est une opération d'équilibrage des valeurs d'histogramme sans nécessiter la valeur moyenne et l'écart type mentionnés ci-dessus. Ceci est défini par l'équation suivante. Cependant, S ... nombre total de valeurs de pixels, Zmax ... valeur maximale des valeurs de pixels, h (z) ... fréquence de densité z ファイル名

A23


def hist_equal(img, z_max=255):
    """
Aplatissement du graphite

    params
    --------------------------------------
    param1: numpy.image au format ndarray
    param2:Valeur de pixel maximale

    returns
    --------------------------------------
    numpy.image au format ndarray
    """

    #Obtenez la hauteur, la largeur et la couleur de l'image
    H, W, C = img.shape
    #Nombre total de valeurs de pixel(Hauteur de l'image x largeur de l'image x nombre de couleurs)
    S = H * W * C * 1.     # 49152.0
    #Copie de l'image
    out = img.copy()

    #Fréquence de concentration
    sum_h = 0.

    #Densité d'image 0~Chaque fréquence jusqu'à 255
    for i in range(256):
        #Où les concentrations correspondent
        ind = np.where(img==i)
        #Fréquence de concentration constante
        sum_h += len(img[ind])
        #Balance des valeurs d'histogramme(Se référer à la formule)
        z_prime = z_max / S * sum_h
        out[ind] = z_prime
    
    out = out.astype(np.uint8)

    return out

#Manipuler l'histogramme
out = hist_equal(img)

#Sauvegarder le résultat
cv2.imwrite(OUT_DIR + 'ans23_1.jpg', out)
#Afficher l'image
cv2_imshow(out)
cv2.waitKey(0)
cv2.destroyAllWindows()

#Afficher un histogramme
plt.hist(out.ravel(), bins=255, rwidth=0.8, range=(0, 255))
plt.savefig("img23_2.png ")
plt.show()

img23_1.png ファイル名

Référence: Hystertic Part 2: Aplatir l'histogramme

Q.24. Correction gamma

Effectuer une correction gamma (c = 1, g = 2,2) sur imori_gamma.jpg. La correction gamma est une correction lorsque la valeur du pixel est convertie de manière non linéaire via un support tel qu'une caméra. Si l'image est affichée telle quelle sur un affichage ou autre, l'écran s'assombrit.Par conséquent, le but de la correction gamma est d'afficher une image excluant les caractéristiques de l'affichage en augmentant la valeur RVB à l'avance. On dit qu'une conversion non linéaire se produit par l'équation suivante. Cependant, x est normalisé à [0,1]. c ... constante, g ... caractéristique gamma (généralement 2,2) ファイル名 Par conséquent, la correction gamma est effectuée par l'équation suivante. ファイル名

A24


def gamma_correction(img, c=1, g=2.2):
    """
Correction gamma: comment régler la luminosité de l'image

    params
    --------------------------------------
    param1: numpy.image au format ndarray
    param2:constant
    param3:Caractéristiques gamma

    returns
    --------------------------------------
    numpy.image au format ndarray
    """

    #Copie de l'image
    out = img.copy().astype(np.float)
    #Diviser par 255(Convertir en Iin)
    out /= 255.
    #Formule de correction gamma
    out = (1/c * out) ** (1/g)

    #Multiplier 255
    out *= 255
    out = out.astype(np.uint8)

    return out

#Correction gamma
out = gamma_correction(img_gamma)

#Sauvegarder le résultat
cv2.imwrite(OUT_DIR + 'ans24.jpg', out)
#Afficher l'image
cv2_imshow(out)
cv2.waitKey(0)
cv2.destroyAllWindows()

img24.png

Référence: Essayez Python!

Q.25. Interpolation du voisin le plus proche

Agrandir l'image 1,5 fois par interpolation du plus proche voisin. Le voisin le plus proche est une méthode qui utilise le pixel le plus proche tel quel lors de l'agrandissement de l'image. C'est simple et la vitesse de traitement est rapide, mais la qualité de l'image se détériore considérablement. Interpolé par l'équation suivante. I '... image après agrandissement, I ... image avant agrandissement, un ... taux d'agrandissement, [] ... arrondi ファイル名

A25


"""
Interpolation du voisin le plus proche
cv2.resize(src, dsize[, interpolation])
image d'entrée src
Taille de l'image après avoir changé dsize
interpolation Méthode d'interpolation(Cv2 pour l'interpolation du plus proche voisin.INTER_NEAREST)
"""
#Interpolation du voisin le plus proche
#Taille de l'image après modification: img.shape>>>(Hauteur, largeur, couleur)
out = cv2.resize(
    img, (int(img.shape[1]*1.5), int(img.shape[0]*1.5)), interpolation=cv2.INTER_NEAREST)

#Sauvegarder le résultat
cv2.imwrite(OUT_DIR + 'ans25.jpg', out)
#Afficher l'image
cv2_imshow(out)
cv2.waitKey(0)
cv2.destroyAllWindows()

img25.png

Référence: [[Python / OpenCV] Agrandissement / réduction de l'image (méthode d'interpolation du plus proche voisin, méthode d'interpolation bilinéaire, méthode d'interpolation bicubique)](https://algorithm.joho.info/programming/python/opencv-resize-nearest- interpolation-py /)

Q.26. Interpolation bi-linéaire

Agrandissez l'image 1,5 fois avec l'interpolation bi-linéaire. L'interpolation bi-linéaire est une méthode pour compléter les quatre pixels environnants en les pondérant en fonction de la distance. Plus la quantité de calcul est élevée, plus le temps de traitement est long, mais la détérioration de la qualité de l'image peut être supprimée.

A26


"""
Méthode d'interpolation bilinéaire (Bi-interpolation linéaire) est une méthode d'interpolation qui utilise les quatre pixels environnants.
cv2.resize(src, dsize[, interpolation])
image d'entrée src
Taille de l'image après avoir changé dsize
interpolation Méthode d'interpolation(Cv2 pour l'interpolation bilinéaire.INTER_LINEAR)
"""
#Méthode d'interpolation bilinéaire
#Taille de l'image après modification: img.shape>>>(Hauteur, largeur, couleur)
out = cv2.resize(
    img, (int(img.shape[1]*1.5), int(img.shape[0]*1.5)), interpolation=cv2.INTER_LINEAR)

#Sauvegarder le résultat
cv2.imwrite(OUT_DIR + 'ans26.jpg', out)
#Afficher l'image
cv2_imshow(out)
cv2.waitKey(0)
cv2.destroyAllWindows()

img26.png

Référence: [[Python / OpenCV] Agrandissement / réduction de l'image (méthode d'interpolation du plus proche voisin, méthode d'interpolation bilinéaire, méthode d'interpolation bicubique)](https://algorithm.joho.info/programming/python/opencv-resize-nearest- interpolation-py /)

Q.27. Interpolation bi-cubique

Agrandissez l'image 1,5 fois avec une interpolation bi-cubique. L'interpolation bi-cubique est une extension de l'interpolation bi-linéaire, et l'interpolation est effectuée à partir des 16 pixels environnants.

A27


"""
La méthode d'interpolation bicubique utilise les valeurs de pixel de 16 pixels environnants.
cv2.resize(src, dsize[, interpolation])
image d'entrée src
Taille de l'image après avoir changé dsize
interpolation Méthode d'interpolation(Cv2 pour l'interpolation bicubique.INTER_CUBIC)
"""
#Interpolation bicubique
#Taille de l'image après modification: img.shape>>>(Hauteur, largeur, couleur)
out = cv2.resize(
    img, (int(img.shape[1]*1.5), int(img.shape[0]*1.5)), interpolation=cv2.INTER_CUBIC)

#Sauvegarder le résultat
cv2.imwrite(OUT_DIR + 'ans27.jpg', out)
#Afficher l'image
cv2_imshow(out)
cv2.waitKey(0)
cv2.destroyAllWindows()

img27.png

Référence: [[Python / OpenCV] Agrandissement / réduction de l'image (méthode d'interpolation du plus proche voisin, méthode d'interpolation bilinéaire, méthode d'interpolation bicubique)](https://algorithm.joho.info/programming/python/opencv-resize-nearest- interpolation-py /)

Q.28. Conversion d'affine (mouvement parallèle)

Utilisez la transformation affine pour déplacer l'image en parallèle de +30 dans la direction x et de -30 dans la direction y. La transformation affine est une opération qui transforme une image à l'aide d'une matrice 3x3.

A28


"""
Conversion d'affine
cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])
Image d'origine (tableau NumPy ndarray) comme premier argument
Matrice de conversion 2 x 3 (tableau NumPy ndarray) comme deuxième argument,
Spécifiez la taille (taple) de l'image de sortie dans le troisième argument.
"""
#Obtenez la hauteur, la largeur et la couleur de l'image
H, W, C = img.shape
#Mouvement parallèle[[1,0,Quantité de mouvement dans le sens latéral],[0,1,Quantité de mouvement dans le sens vertical]]Matrice 2x3
M = np.float64([[1, 0, 30], [0,1,-30]])
#Conversion d'affine
out = cv2.warpAffine(img, M, (W, H))

#Sauvegarder le résultat
cv2.imwrite(OUT_DIR + 'ans28.jpg', out)
#Afficher l'image
cv2_imshow(out)
cv2.waitKey(0)
cv2.destroyAllWindows()

img28.png

Référence: [Python / OpenCV] Faire pivoter l'image avec conversion affine

Q.29. Conversion d'affine (agrandissement / réduction)

Utilisez la transformation affine pour (1) redimensionner 1,3 fois dans la direction x et 0,8 fois dans la direction y. De plus, en plus des conditions (2) et (1), réalisez un mouvement parallèle de +30 dans la direction x et de -30 dans la direction y en même temps.

A29



def affine_expand(img, ratio_x, ratio_y):
    """
Agrandir avec conversion affine

    params
    -------------------------------
    param1: numpy.image au format ndarray
    param2:Rapport de direction X
    param3:Rapport dans la direction y

    returns
    -------------------------------
    numpy.image au format ndarray
    """
    #Hauteur et largeur de l'image
    H, W = img.shape[:2]
    #coordonnées xy np.type float32
    src = np.array([[0.0, 0.0],[0.0, 1.0],[1.0, 0.0]], np.float32)
    # x,y Multipliez chaque rapport
    dest = src.copy()
    dest[:,0] *= ratio_x
    dest[:,1] *= ratio_y
    """
Générer une matrice de transformation pour une transformation affine: cv2.getAffineTransform(src, dest)
    src:Coordonnées de 3 points avant conversion
    dest:Spécifiez les coordonnées des trois points après la conversion avec le tableau NumPy ndarray
    """
    affine = cv2.getAffineTransform(src, dest)
    """
Conversion d'affine
    cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])
Image d'origine (tableau NumPy ndarray) comme premier argument
Matrice de conversion 2 x 3 (tableau NumPy ndarray) comme deuxième argument,
Spécifiez la taille (taple) de l'image de sortie dans le troisième argument.
    INTER_LANCZOS4 - Interpolation de Lanczos utilisant la zone de voisinage de 8 × 8
    """
    return cv2.warpAffine(img, affine, (int(W*ratio_x), int(H*ratio_y)), cv2.INTER_LANCZOS4) #La méthode d'interpolation peut également être spécifiée


#Agrandir avec conversion affine
out = affine_expand(img, 1.3, 0.8)
#Mouvement parallèle[[1,0,Quantité de mouvement dans le sens latéral],[0,1,Quantité de mouvement dans le sens vertical]]Matrice 2x3
H, W = out.shape[:2]
M = np.float64([[1, 0, 30], [0,1,-30]])
out2 = cv2.warpAffine(out, M, (W, H))

#Sauvegarder le résultat
cv2.imwrite(OUT_DIR + 'ans29_1.jpg', out)
cv2.imwrite(OUT_DIR + 'ans29_2.jpg', out2)

#Afficher l'image
cv2_imshow(out)
cv2_imshow(out2)
cv2.waitKey(0)
cv2.destroyAllWindows()

img29_1.pngimg29_2.png

Référence: Comprendre complètement la conversion Affin

Q.30. Conversion d'affine (rotation)

(1) Faites pivoter 30 degrés dans le sens antihoraire en utilisant la transformation affine. (2) Créez une image de sorte qu'il y ait le moins de zones noires possible en fixant les coordonnées centrales avec une image tournée de 30 degrés dans le sens antihoraire à l'aide de la transformation Affin. (Cependant, si vous effectuez une simple conversion affine, l'image sera coupée, vous devez donc être créatif.)

A30


def affin_rotate(img, x, y, theta, scale):
    """
Rotation avec conversion affine

    params
    -------------------------------
    param1: numpy.image au format ndarray
    param2:Coordonnée X de l'axe de rotation
    param3:Coordonnée Y de l'axe de rotation
    param4:Angle de rotation
    param5:Angle de rotation / grossissement

    returns
    -------------------------------
    numpy.image au format ndarray
    """

    """
Transformation d'affine représentant une rotation bidimensionnelle
    cv2.getRotationMatrix2D(center, angle, scale)
    center:Coordonnées qui sont à l'origine de la rotation
    angle:Angle de rotation (degré degré, pas radian)
    scale:Rapport agrandissement / réduction.
    """
    #Calcul de la matrice de conversion de rotation
    R = cv2.getRotationMatrix2D((x, y), theta, scale)
    """
Conversion d'affine
    cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])
Image d'origine (tableau NumPy ndarray) comme premier argument
Matrice de conversion 2 x 3 (tableau NumPy ndarray) comme deuxième argument,
Spécifiez la taille (taple) de l'image de sortie dans le troisième argument.
    cv2.INTER_CUBIC:Bicubique
    """
    #Conversion d'affine
    dst = cv2.warpAffine(img, R, gray.shape,
                        flags=cv2.INTER_CUBIC)

    return dst

#Coordonnées du centre de l'image
oy, ox = int(img.shape[0]/2), int(img.shape[1]/2)

#Rotation de 30 degrés dans le sens antihoraire
out1 = affin_rotate(img, 0, 0, 30, 1)
#Coordonnées centrales fixes avec image tournée de 30 degrés dans le sens antihoraire
out2 = affin_rotate(img, ox, oy, 30, 1)

#Sauvegarder le résultat
cv2.imwrite(OUT_DIR + 'ans30_1.jpg', out1)
cv2.imwrite(OUT_DIR + 'ans31_2.jpg', out2)

#Afficher l'image
cv2_imshow(out1)
cv2_imshow(out2)
cv2.waitKey(0)
cv2.destroyAllWindows()

img30_1.pngimg30_2.png

Référence: Conversion géométrique avec Python, OpenCV (conversion affine, conversion de projection, etc.) Référence: [Python / OpenCV] Faire pivoter l'image avec transformation affine

Impressions

On a l'impression que le niveau augmente progressivement. Essayez d'implémenter autant que possible OpenCV.

Recommended Posts

100 coups sur le traitement d'image !! (021-030) Je veux faire une pause ...
Je ne veux pas passer un test de codage
Je veux imprimer dans la notation d'inclusion
Je veux créer un environnement Python
Traitement d'image 100 coups ①
Python: je souhaite mesurer proprement le temps de traitement d'une fonction
Je veux faire de matplotlib un thème sombre
Je souhaite créer facilement un modèle de bruit
Je veux INSÉRER un DataFrame dans MSSQL
Je veux créer une fenêtre avec Python
Je veux faire un jeu avec Python
Je souhaite créer un type d'implémentation pouvant être branché
Je veux trouver facilement une délicieuse boutique
Je veux écrire dans un fichier avec Python
Je souhaite télécharger une application Django sur heroku
Je veux convertir une image en WebP avec sucette
Je souhaite intégrer une variable dans une chaîne Python
Je veux facilement implémenter le délai d'expiration en python
Je veux répéter plusieurs fois un générateur Python
Je veux que DQN Puniki frappe un home run
Je veux donner un group_id à une trame de données pandas
Je veux générer rapidement UUID (memo memo) ~ Edition Python ~
Je veux faire la transition avec un bouton sur le ballon
Je veux escalader une montagne avec l'apprentissage par renforcement
Je veux écrire en Python! (2) Écrivons un test
Je veux trouver un package populaire sur PyPi
Je veux échantillonner au hasard un fichier avec Python
Je souhaite créer facilement un environnement de développement basé sur un modèle
Je veux travailler avec un robot en python.
Je veux diviser une chaîne de caractères avec hiragana
Je souhaite installer un package de Php Redis
[Python] Je veux faire d'une liste imbriquée un taple
Je souhaite créer manuellement une légende avec matplotlib
Je souhaite envoyer automatiquement un e-mail de création d'entreprise
Comment prendre une image capturée à partir d'une vidéo (OpenCV)
Je veux faire fonctionner un ordinateur quantique avec Python
Je veux lier une variable locale avec lambda
Je voulais collecter beaucoup d'images, j'ai donc essayé d'utiliser "google image download"
Je souhaite prendre une capture d'écran du site sur Docker en utilisant n'importe quelle police
Je veux un générateur de mox
opencv-python Introduction au traitement d'image
100 coups sur le traitement d'image !! (011-020) Début de partie
100 coups sur le traitement d'image !! (001 --010) Soigneusement et soigneusement
Je veux résoudre SUDOKU
Je veux un générateur mox (2)
Je veux créer un éditeur de blog avec l'administrateur de django
Je veux démarrer un environnement Jupyter avec une seule commande
[Python] Je souhaite obtenir un ensemble commun entre numpy
Je veux démarrer beaucoup de processus à partir de python
Je veux faire une macro de clic avec pyautogui (désir)
Je veux générer automatiquement un nom de groupe de metal moderne
Je veux faire une macro de clic avec pyautogui (Outlook)
Je souhaite utiliser un environnement virtuel avec jupyter notebook!
Je veux installer le package de requirements.txt avec poésie
Je souhaite envoyer un message de Python à LINE Bot
[Visualisation] Je veux dessiner un beau graphique avec Plotly
Je veux ajouter un joli complément à input () en python
Je veux créer un Dockerfile pour le moment.
Je souhaite utiliser un caractère générique que je souhaite décortiquer avec Python remove
Je veux comprendre à peu près systemd