Résumé de l'exécution du traitement d'image (manipulation des pixels) en Python. Pour l'apprentissage du traitement d'image, les performances et la qualité sont secondaires et la clarté est importante.
L'environnement est Mac. En termes d'approche académique, le langage est Python et la version 2.7.x.
Python
Mac est livré avec Python depuis le début.
python --version
S'il vous plaît essayez. Si non,
brew install python
Je vais y entrer.
On suppose que l'infusion est incluse. .. ..
Installez pip, un outil de gestion de packages Python, pour faciliter l'installation de la bibliothèque.
easy_install pip
Cette fois, nous utiliserons numpy et Pillow (PIL). numpy comprend des outils pratiques pour les calculs et Pillow comprend des outils liés au traitement d'image.
pip install numpy
pip install pillow
Pour le moment, je vais charger l'image et l'afficher.
from PIL import Image
im = Image.open("./achan.jpg ")
im.show()
Il est juste affiché, alors faisons-le pivoter et affichons-le.
from PIL import Image
im = Image.open("./achan.jpg ")
im.rotate(30).show()
Je pense qu'il a été tourné de 30 degrés dans le sens antihoraire autour du centre de l'image.
En pratique, c'est bien, mais je ne sais pas ce que ça fait en interne. Donc, ici, je voudrais écrire un programme qui traite et fait pivoter chaque pixel.
Maintenant, travaillons avec les pixels individuels.
Maintenant, effectuons un traitement d'inversion négatif-positif, qui est un traitement d'opération de pixel typique et simple.
#coding:utf-8
from PIL import Image
#Chargement des images
im = Image.open("./achan.jpg ")
#Convertir en RVB
rgb_im = im.convert('RGB')
#Obtenir la taille de l'image
size = rgb_im.size
#Créer une nouvelle image vide avec la même taille que la taille acquise
im2 = Image.new('RGBA',size)
#loop
#x
for x in range(size[0]):
#y
for y in range(size[1]):
#Obtenez des pixels
r,g,b = rgb_im.getpixel((x,y))
#Traitement d'inversion
r = 255 - r
g = 255 - g
b = 255 - b
#set pixel
im2.putpixel((x,y),(r,g,b,0))
#show
im2.show()
Il a été retourné à un négatif.
L'échelle de gris est grise lorsque r, g et b ont la même valeur. Cependant, il est au cas par cas de déterminer s'il faut faire la même valeur selon une telle règle. Ici, nous allons obtenir la valeur moyenne de r, g et b et utiliser cette valeur (ci-après, seule l'opération de pixel est extraite).
#loop
#x
for x in range(size[0]):
#y
for y in range(size[1]):
#Obtenez des pixels
r,g,b = rgb_im.getpixel((x,y))
#Moyenne
g = (r + g + b)/3
#set pixel
im2.putpixel((x,y),(g,g,g,0))
#show
im2.show()
Il est devenu gris pour le moment.
Il existe plusieurs façons de faire pivoter une image, mais la plus primitive consiste à utiliser une matrice de rotation.
La matrice de rotation est exprimée par la formule suivante. Si vous donnez à θ l'angle que vous souhaitez faire pivoter en radian, vous pouvez faire pivoter un siège (x2, y2) de cet angle.
\begin{equation}
\begin{pmatrix}
x_{2} \\
y_{2}
\end{pmatrix}
=
\begin{pmatrix}
\cos \theta & -\sin \theta \\
\sin \theta & \cos \theta
\end{pmatrix}
\begin{pmatrix}
x_{1} \\
y_{2}
\end{pmatrix}
\end{equation}
En Python, en utilisant le module numpy, la matrice de rotation ci-dessus peut être modifiée.
m_matrix = np.matrix([
[np.cos(rad),-1*np.sin(rad)],
[np.sin(rad),np.cos(rad)]
])
Il est très pratique car il peut être exprimé intuitivement, et la somme et le produit peuvent être obtenus en le décrivant comme une opération normale à quatre règles.
J'utilise matrice ici, mais à moins que vous n'ayez une raison spécifique, il semble préférable d'utiliser array.
Maintenant, écrivons un code qui tourne à l'aide d'une matrice de rotation. Dans le code ci-dessous, le coin supérieur gauche est traité comme l'axe de rotation, et non comme le centre de l'image. De plus, comme putpixel, qui ne peut gérer que int, est utilisé, des irrégularités se produisent dans l'image (bien que cette méthode soit utilisée ici par souci de clarté).
#coding:UTF-8
from PIL import Image
import numpy as np
#Chargement des images
im = Image.open("./achan.jpg ")
#Convertir en RVB
rgb_im = im.convert('RGB')
#Obtenir la taille de l'image
size = rgb_im.size
#Créer une nouvelle image vide avec la même taille que la taille acquise
im2 = Image.new('RGBA',size)
#loop
#x
for x in range(size[0]):
#y
for y in range(size[1]):
#Obtenez des pixels
r,g,b = rgb_im.getpixel((x,y))
#En traitement
#30 degrés
rad = np.pi/6
#Matrice de rotation
m_matrix = np.matrix([
[np.cos(rad),-1*np.sin(rad)],
[np.sin(rad),np.cos(rad)]
])
#Coordonnées applicables (coordonnées d'origine)
p_matrix = np.matrix([
[x],
[y]
])
#Fonctionnement de la matrice
p2_matrix = m_matrix * p_matrix
#Travaillez après avoir déménagé(Seul int peut être mis, alors convertissez-le en int)
x2 = int(p2_matrix[0,0])
y2 = int(p2_matrix[1,0])
#S'il est dans la taille de l'image
if 0 < x2 < size[0] and 0 < y2 < size[1]:
#Spécifiez le RVB d'origine pour les coordonnées après le déplacement
im2.putpixel((x2,y2),(r,g,b,0))
#show
im2.show()
L'inversion par rapport à l'axe x, l'axe y, l'axe arbitraire, etc. peut également être effectuée avec une matrice. Il s'agit de la première conversion des mathématiques du secondaire. Par exemple, l'inversion de l'axe y est donnée ci-dessous.
\begin{equation}
\begin{pmatrix}
x_{2} \\
y_{2}
\end{pmatrix}
=
\begin{pmatrix}
-1 & 0 \\
0 & 1
\end{pmatrix}
\begin{pmatrix}
x_{1} \\
y_{2}
\end{pmatrix}
\end{equation}
Cette matrice est en Python
#cible de l'axe y
y_matrix = np.matrix([
[-1,0],
[0,1]
])
Peut être exprimé comme.
Maintenant écrivons le code. Si vous inversez normalement l'axe y, tous les points se déplaceront dans la direction négative et ne seront pas dessinés. Par conséquent, déplacez-le en parallèle de la largeur (axe des x) de l'image.
#coding:UTF-8
from PIL import Image
import numpy as np
#Chargement des images
im = Image.open("./achan.jpg ")
#Convertir en RVB
rgb_im = im.convert('RGB')
#Obtenir la taille de l'image
size = rgb_im.size
#Créer une nouvelle image vide avec la même taille que la taille acquise
im2 = Image.new('RGBA',size)
#loop
#x
for x in range(size[0]):
#y
for y in range(size[1]):
#Obtenez des pixels
r,g,b = rgb_im.getpixel((x,y))
#En traitement
#cible de l'axe y
y_matrix = np.matrix([
[-1,0],
[0,1]
])
#Coordonnées applicables (coordonnées d'origine)
p_matrix = np.matrix([
[x],
[y]
])
#Fonctionnement de la matrice
p2_matrix = y_matrix * p_matrix
#Travaillez après avoir déménagé(Seul int peut être mis, alors convertissez-le en int)
x2 = int(p2_matrix[0,0]) + size[0] #Mouvement parallèle de la coordonnée x par la taille horizontale de l'addition
y2 = int(p2_matrix[1,0])
#S'il est dans la taille de l'image
if 0 < x2 < size[0] and 0 < y2 < size[1]:
#Spécifiez le RVB d'origine pour les coordonnées après le déplacement
im2.putpixel((x2,y2),(r,g,b,0))
#show
im2.show()
C'était inversé. Inversion dite gauche-droite. On a l'impression que c'est un pixel supplémentaire. .. .. Je m'en fiche ici.
Comme pour le calcul matriciel, nous allons essayer le traitement de voisinage, qui est un traitement essentiel dans le traitement d'image. Le traitement de proximité est utile pour le «traitement de flou» et «l'extraction de contours».
Ici, nous allons essayer un "processus de flou" relativement simple. Il existe différents algorithmes, mais ici nous allons essayer la méthode la plus simple pour obtenir la valeur moyenne du voisinage de 8 et la définir.
Huit quartiers sont huit zones qui entourent les coordonnées de référence.
Obtenez les valeurs r, g, b de chacune de ses coordonnées et faites leur moyenne.
Une mise en garde est que x-1 n'existe pas ou que x + 1 s'étend au-delà des coordonnées des bords de l'image, de sorte qu'un traitement est nécessaire. Maintenant écrivons le code.
#coding:utf-8
from PIL import Image
#Chargement des images
im = Image.open("./achan.jpg ")
#Convertir en RVB
rgb_im = im.convert('RGB')
#Obtenir la taille de l'image
size = rgb_im.size
#Créer une nouvelle image vide avec la même taille que la taille acquise
im2 = Image.new('RGBA',size)
#loop
#x
for x in range(size[0]):
#y
for y in range(size[1]):
#Obtenez des pixels des coordonnées de la cible
r0,g0,b0 = rgb_im.getpixel((x,y))
#Initialisation (pour le moment, définissez les valeurs de coordonnées actuelles sur toutes les valeurs voisines)
r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r0;
g1 = g2 = g3 = g4 = g5 = g6 = g7 = g8 = g0;
b1 = b2 = b3 = b4 = b5 = b6 = b7 = b8 = b0;
#Obtenez la valeur des coordonnées du quartier
#1
if x-1 > 0 and y+1 < size[1]:
r1,g1,b1 = rgb_im.getpixel((x-1,y+1))
#2
if y+1 < size[1]:
r2,g2,b2 = rgb_im.getpixel((x,y+1))
#3
if x+1 < size[0] and y+1 < size[1]:
r3,g3,b3 = rgb_im.getpixel((x+1,y+1))
#4
if x-1 > 0:
r4,g4,b4 = rgb_im.getpixel((x-1,y))
#5
if x+1 < size[0]:
r5,g5,b5 = rgb_im.getpixel((x+1,y))
#6
if x-1 > 0 and y-1 > 0:
r6,g6,b6 = rgb_im.getpixel((x-1,y-1))
#7
if y-1 > 0:
r7,g7,b7 = rgb_im.getpixel((x,y-1))
#8
if x+1 < size[0] and y-1 > 0:
r8,g8,b8 = rgb_im.getpixel((x+1,y-1))
#Averize RVB à proximité
r = (r0 + r1 + r2 + r3 + r4 + r5 + r6 + r7 + r8)/9
g = (g0 + g1 + g2 + g3 + g4 + g5 + g6 + g7 + g8)/9
b = (b0 + b1 + b2 + b3 + b4 + b5 + b6 + b7 + b8)/9
#dessin
im2.putpixel((x,y),(r,g,b,0))
#show
im2.show()
C'est un peu déroutant, mais c'est flou. Divers flous sont possibles en élargissant davantage le voisinage et en concevant l'algorithme.
C'est encore un long chemin pour le rendre pratiquement utilisable, comme la correction des pixels, mais pour le moment, le contenu de base est à la hauteur.