[PYTHON] Lire le traitement d'image numérique

J'étudie avec un livre intitulé Digital Image Processing. J'ai implémenté (conversion de contraste) dans le but d'approfondir la compréhension.

* Conversion de contraste de luminosité *

Le contraste est le degré de changement de luminosité et de couleur. (Interprétation personnelle) Fort contraste → Facile à comprendre la luminosité et le transfert des couleurs, facile à comprendre le contour d'un objet. Contraste faible → Il est difficile de comprendre la luminosité et le transfert des couleurs, et il est difficile de comprendre le contour d'un objet.

* Courbe de tonalité *

En modifiant la relation entre l'entrée et la sortie, la tonalité de couleur de l'image peut être modifiée. Par conséquent, il devient facile à voir ou difficile à voir.

* La première pièce à utiliser cette fois *

Utilisez un échantillon sombre comme celui de l'image ci-dessous pour faciliter la visualisation de l'effet.

Caractéristiques: assez sombre

python


#Bibliothèques requises
import cv2
import numpy as np
import matplotlib.pyplot as plt

#Chemin de la photo
pic_path = 'pet-bottle-pic/test/camera_pic/aquari3.jpg'

#Lis
pic_image = cv2.imread(pic_path)

#Convertir en gris
pic_image = cv2.cvtColor(pic_image, cv2.COLOR_BGR2GRAY)

#Lorsqu'il est lu avec cv, plt.cmap lors de l'utilisation d'imshow='gray'Notez qu'il ne sera pas gris sauf si vous spécifiez
plt.imshow(pic_image, cmap='gray')
plt.title('sample_dark')
plt.savefig("aquari_dark.jpg ")

↓ C'est sombre et presque invisible

aquari_dark.jpg

python


#Pixel
pic_image.shape # (2464, 3280)

Distribution des valeurs de pixel

python


#Aplatir dans une dimension pour créer un histogramme
flat_data = np.ravel(pic_image)

#Portée de la barre
bins_range = range(0, 260, 5)

#Histogramme de sortie
plt.hist(flat_data, bins = bins_range)
plt.title('sample_dark')
plt.xlabel('pixel_value')
plt.ylabel('frequency')
plt.savefig("hist_aquari_dark.png ")

↓ Il y a un biais du côté noir.

hist_aquari_dark.png

Mise en œuvre de la conversion de contraste

* Type de ligne brisée *

Selon la façon dont il est fait, le contraste dans n'importe quelle plage peut être augmenté. (Bien que ce soit un peu artificiel) Étant donné que l'image échantillon est dense dans la plage de valeurs de pixel de 0 à 50, l'angle est défini dans cette plage.

python


def bend_line(X):
    y = X*5
    y = np.where(y>=255, 255, y)
    return y

Appliquez une fonction qui sort comme indiqué dans le graphique ci-dessous.

python


X = np.arange(0, 255, 1)
y = bend_line(X)

plt.title('sample_dark_bend_line')
plt.xlabel('INPUT')
plt.ylabel('OUTPUT')
plt.plot(X, y)
plt.savefig("bend_line.png ")

bend_line.png

Photo après application

python


pic_func1 = bend_line(pic_image)
plt.imshow(pic_func1, cmap='gray')
plt.title('sample_dark_after_bend_line')
plt.savefig("aquari_dark_after_bend_line.jpg ")

↓ Vous pouvez maintenant voir la bouteille en PET. (Même si ça a l'air un peu sale)

aquari_dark_after_bend_line.jpg

Regardons la distribution.

python


flat_data = np.ravel(pic_func1)

bins_range = range(0, 260, 5)
 
#Histogramme de sortie
plt.hist(flat_data, bins = bins_range)
plt.title('sample_dark_after_bend_line')
plt.xlabel('pixel_value')
plt.ylabel('frequency')
plt.savefig("hist_aquari_dark_after_bend_line.png ")

↓ La distribution a été un peu lissée.

hist_aquari_dark_after_bend_line.png

* Courbe de tonalité multipliée (correction gamma) *

Convient pour corriger des images trop sombres ou trop lumineuses pour être comprises. Convient pour augmenter le contraste des images avec une distribution près des bords.

Implémentez la formule suivante appelée fonction gamma. $ y = \left( \frac{X}{255} \right)^\frac{1}{\gamma} \times 255\\ $ À propos, sur le site officiel d'Opencv, 1 / γ est introduit comme γ.

python


def g_function(X, gamma):
    y = 255*(X/255)**(1/gamma)
    return y

Graphique pour chaque valeur γ

python


X = np.arange(0, 255, 1)
gamma = [3, 2, 1.5, 1, 0.5, 0.33]
labels = ["3", "2", "1.5", "1", "0.5", "0.33"]

plt.title('g_function')
plt.xlabel('INPUT')
plt.ylabel('OUTPUT')

for g, l in zip(gamma, labels):
    y = g_function(X, g)
    plt.plot(X, y, label = l)
plt.legend()


plt.savefig("g_function.png ")

g_function.png

γ est grand → Renforce le contraste des images sombres dans leur ensemble. γ est petit → Augmente globalement le contraste des images lumineuses.

python


gamma = 3
pic_gfunc = g_function(pic_image, gamma)
plt.imshow(pic_gfunc, cmap='gray')
plt.title('sample_dark_after_gfunc')
plt.savefig("aquari_dark_after_gfunc.jpg ")

↓ C'est assez propre.

aquari_dark_after_gfunc.jpg

python


flat_data = np.ravel(pic_gfunc)

bins_range = range(0, 260, 5)
 
#Histogramme de sortie
plt.hist(flat_data, bins = bins_range)
plt.title('sample_dark_after_gfunc')
plt.xlabel('pixel_value')
plt.ylabel('frequency')
plt.savefig("hist_aquari_dark_after_gfunc.png ")

↓ De même, la distribution est lissée.

hist_aquari_dark_after_gfunc.png

* Image suivante à utiliser

Caractéristiques: Normal

python


#Chemin de la photo
pic_path = 'pet-bottle-pic/test/camera_pic/aquari.jpg'

#Lis
pic_image = cv2.imread(pic_path)

#Convertir en gris
pic_image = cv2.cvtColor(pic_image, cv2.COLOR_BGR2GRAY)

#Lorsqu'il est lu avec cv, plt.cmap lors de l'utilisation d'imshow='gray'Notez qu'il ne sera pas gris sauf si vous spécifiez
plt.imshow(pic_image, cmap='gray')
plt.title('sample_normal')
plt.savefig("aquari.jpg ")

aquari.jpg

Distribution des valeurs de pixel

python


#Aplatir dans une dimension pour créer un histogramme
flat_data = np.ravel(pic_image)

#Portée de la barre
bins_range = range(0, 260, 5)

#Histogramme de sortie
plt.hist(flat_data, bins = bins_range)
plt.title('sample_normal')
plt.xlabel('pixel_value')
plt.ylabel('frequency')
plt.savefig("hist_aquari.png ")

hist_aquari.png

* Type de courbe en forme de S *

Convient pour augmenter le contraste des images avec une distribution proche du centre. Mettre en œuvre la formule suivante $ y = \frac{255}{1 + \exp^{a\left(-X + 127\right)}}\\ $

python


def s_func(X, a):
    y = 255/(1 + np.exp(a*(-1*X + 127)))
    return y

python


X = np.arange(0, 255, 1)
a = 0.05
y = s_func(X, a)

plt.title('s_function')
plt.xlabel('INPUT')
plt.ylabel('OUTPUT')

plt.plot(X, y)
plt.savefig("s_function.png ")

s_function.png

python


a = 0.05
y = s_func(pic_image, a)
plt.imshow(y, cmap='gray')
plt.title('sample_after_sfunc')
plt.savefig("aquari_after_sfunc.jpg ")

↓ C'était un peu clair.

aquari_after_sfunc.jpg

python


flat_data = np.ravel(y)

bins_range = range(0, 260, 5)
 
#Histogramme de sortie
plt.hist(flat_data, bins = bins_range)
plt.title('sample_after_sfunc')
plt.xlabel('pixel_value')
plt.ylabel('frequency')
plt.savefig("hist_aquari_sfunc.png ")

↓ L'histogramme est devenu plat.

hist_aquari_sfunc.png

* Effets spéciaux *

Il y a un aspect mystérieux dans son utilisation, mais je l'ai implémenté.

* Inverser *

Lumineux → sombre Sombre → brillant devenir.

python


def rev_func(X):
    y = -X + 255
    return y

python


X = np.arange(0, 255, 1)
y = rev_func(X)

plt.title('Rev_function')
plt.xlabel('INPUT')
plt.ylabel('OUTPUT')
plt.plot(X, y)
plt.savefig("rev_func.png ")

rev_func.png

python


y = rev_func(pic_image)
plt.imshow(y, cmap='gray')
plt.title('sample_after_rev_func')
plt.savefig("aquari_after_rev_func.jpg ")

aquari_after_rev_func.jpg

python


flat_data = np.ravel(y)

bins_range = range(0, 260, 5)
 
#Histogramme de sortie
plt.hist(flat_data, bins = bins_range)
plt.title('sample_after_rev_func')
plt.xlabel('pixel_value')
plt.ylabel('frequency')
plt.savefig("hist_aquari_rev_func.png ")

↓ La distribution est également inversée à gauche et à droite.

hist_aquari_rev_func.png

* Postérisation *

Cela ressemble à une affiche.

Luminosité divisée en 4 étapes

Intervalle: 64 Première étape: 64 Deuxième étape: 128 Troisième étape: 192 Quatrième étape: 255

python


def post_func(X):
    y = np.where(X>=192, 255, X)
    y = np.where((y >=128 ) & (y < 192), 170, y)
    y = np.where((y >=64 ) & (y < 128), 85, y)
    y = np.where(y<64, 0, y)
    return y

python


X = np.arange(0, 255, 1)
y = post_func(X)

plt.title('post_function')
plt.xlabel('INPUT')
plt.ylabel('OUTPUT')
plt.plot(X, y)
plt.savefig("post_func.png ")

post_func.png

python


y = post_func(pic_image)
plt.imshow(y, cmap='gray')
plt.title('sample_after_after_postfunc')
plt.savefig("aquari_after_postfunc.jpg ")

↓ Comme une affiche

aquari_after_postfunc.jpg

python


flat_data = np.ravel(y)

bins_range = range(0, 260, 5)
 
#Histogramme de sortie
plt.hist(flat_data, bins = bins_range)
plt.title('sample_after_postfunc')
plt.xlabel('pixel_value')
plt.ylabel('frequency')
plt.savefig("hist_aquari_postfunc.png ")

hist_aquari_postfunc.png

* Binarisation *

Noir et blanc clair]

python


def to_func(X):
    y = np.where(X>=127, 255, X)
    y = np.where(y<127, 0, y)
    return y

python


X = np.arange(0, 255, 1)
y = to_func(X)

plt.title('2_function')
plt.xlabel('INPUT')
plt.ylabel('OUTPUT')
plt.plot(X, y)
plt.savefig("2_func.png ")

2_func.png

python


y = to_func(pic_image)
plt.imshow(y, cmap='gray')
plt.title('sample_after_after_tofunc')
plt.savefig("aquari_after_tofunc.jpg ")

↓ Est-ce difficile de voir le contraire?

aquari_after_tofunc.jpg

python


flat_data = np.ravel(y)

bins_range = range(0, 260, 5)
 
#Histogramme de sortie
plt.hist(flat_data, bins = bins_range)
plt.title('sample_after_totfunc')
plt.xlabel('pixel_value')
plt.ylabel('frequency')
plt.savefig("hist_aquari_tofunc.png ")

↓ Il est binarisé.

hist_aquari_tofunc.png

* Solarisation *

Cela ressemble à un film lors du développement d'une photo.

python


from math import pi

def sora_func(X):
    X = (3*pi/255)*X
    y = -127.5*(np.cos(X))+127.5
    return y

python


X = np.arange(0, 255, 1)
y = sora_func(X)

plt.title('sora_function')
plt.xlabel('INPUT')
plt.ylabel('OUTPUT')
plt.plot(X, y)
plt.savefig("sora_func.png ")

sora_func.png

python


y = sora_func(pic_image)
plt.imshow(y, cmap='gray')
plt.title('sample_after_sorafunc')
plt.savefig("aquari_after_sorafunc.jpg ")

↓ D'une certaine manière, ça ressemble à ça

aquari_after_sorafunc.jpg

python


flat_data = np.ravel(y)

bins_range = range(0, 260, 5)
 
#Histogramme de sortie
plt.hist(flat_data, bins = bins_range)
plt.title('sample_after_soratfunc')
plt.xlabel('pixel_value')
plt.ylabel('frequency')
plt.savefig("hist_aquari_sorafunc.png ")

hist_aquari_sorafunc.png

Fin

Recommended Posts

Lire le traitement d'image numérique
[Traitement d'image] Postérisation
Traitement d'image 100 coups ①
Traitement d'image avec MyHDL
Premier traitement d'image Python
Traitement d'image avec Python
Traitement d'image avec PIL
Traitement d'image avec Python (partie 2)
opencv-python Introduction au traitement d'image
Traitement d'image avec PIL (Pillow)
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
Traitement d'image avec Python (partie 1)
Traitement d'image avec Python (3)
Traitement d'image par python (Pillow)
Collection de traitement d'image en Python
Traitement de l'expansion et de la contraction de l'image
[Python] Traitement d'image avec scicit-image
Principes de base du traitement d'image en temps réel avec opencv
Notes personnelles pour le traitement d'images python
Traitement d'image avec la binarisation Python 100 knocks # 3
Traitement d'image 100 coups Q9, Q10 (filtre) speedup
Grattage écologique grâce au traitement d'image
100 traitement d'image par Python Knock # 2 Échelle de gris
Traitement d'image | prédire les espèces à partir d'images
Bases du traitement d'images binarisées par Python
Traitement d'image par le remplacement du canal Python 100 Knock # 1
Créer une visionneuse de traitement d'image avec PySimpleGUI
100 traitement d'image avec Python Knock # 8 Max Pooling
Échelle de gris par matrice-Reinventor of Python image processing-
Traitement d'image avec Python et OpenCV [Tone Curve]
Traitement d'image par Python 100 knock # 12 motion filter
Traitement d'image par Python 100 Knock # 6 Traitement de réduction de couleur
Dessin avec Matrix-Reinventor of Python Image Processing-
Traitez facilement des images en Python avec Pillow
Traitement d'image avec Python 100 knocks # 7 pooling moyen
Traitement d'image 100 coups Q.6. Explication du traitement de réduction de couleur
Traitement d'image léger avec Python x OpenCV
Traitement d'image avec Lambda + OpenCV (création d'image grise)
Filtrage par convolution par matrice-Reinventor of Python image processing-
Traitement d'image par Python 100 knock # 9 Filtre Gaussien