Je viens de commencer à utiliser ʻOpneCV` en Python J'ai essayé diverses choses et j'ai trébuché Je vais l'écrire dur.
Quand tu le prends et que tu parles
** LUT
est incroyable! **
j'ai pensé
** J'ai essayé d'utiliser LUT
! **
C'est le contenu.
(En conséquence) J'ai également comparé les performances avec ma propre fonction de conversion des couleurs.
Terminal: Windows 10
Console: cmd(invite de commande)
python:3.6.8
Environnement virtuel: venv
Si vous voulez rendre cmd confortable, cliquez ici >> [https://qiita.com/RoaaaA/items/694ae4ccfa4a69fc8286)
J'ai appris la vision par ordinateur (CV) dans une classe universitaire (paperasse). Pour la première fois, je suis tombé sur quelque chose qui s'appelle «** courbe de tonalité **». Qu'est-ce qu'une courbe de tonalité [^ 1]
Chaque pixel de l'image numérique a une valeur (valeur de pixel) qui représente la teinte. Pour changer la teinte de l'image, comment associer la valeur de pixel de l'image de sortie à la valeur de pixel de l'image d'entrée. La fonction qui donne une telle correspondance est appelée fonction de transformation de niveau de gris, et sa représentation graphique est appelée courbe de ton.
En regardant le net, il semble familier à ceux qui aiment les caméras.
Parmi les courbes de ton apparaissant dans le manuel, il y avait les deux suivantes. (* Bien sûr, beaucoup d'autres sont apparus)
L'axe horizontal correspond à la ** valeur de pixel d'entrée ** et l'axe vertical à la ** valeur de pixel de sortie (convertie) **.
Figure 1 | Figure 2 |
Mettre tout simplement ** Conversion pour augmenter le contraste ** et ** Conversion qui réduit le contraste **.
Cette partie de la classe était déjà il y a plus de six mois. Je voulais en fait appliquer cette courbe de ton à l'image.
Exprimé en fonction, il se présente comme suit (x est la valeur du pixel d'entrée de 0 à 255).
Fonction dans la figure 1:
f(x) = \begin{cases} 2 \cdot x & (x < 128) \\ 255 & (otherwise)
\end{cases}
Fonction dans la figure 2:
f(x) = \begin{cases} 0 & (x < 128) \\ 2 \cdot x - 255 & (otherwise)
\end{cases}
Il semble que cela puisse être généralisé, mais laissons cela pour le moment.
Tout d'abord, j'ai décidé d'écrire le code illustré à la figure 1. Mais ... il est resté bloqué immédiatement.
Quand je suis venu avec la fonction ci-dessus J'ai pensé que je pourrais simplement doubler les valeurs des éléments du tableau original de valeurs de pixels.
Fonction de conversion
def toneCurve(frame):
return 2 * frame
frame = cv2.imread('.\\image\\castle.jpg')
cv2.imwrite('cas.jpg', toneCurve(frame))
frame
est un tableau de valeurs de pixels
Mais ça n'a pas marché. L'image de sortie est la suivante.
L'image originale | Image convertie |
---|---|
Apparemment, si vous doublez simplement la valeur de pixel obtenue par cv2.imread ()
Tout ce qui est supérieur à 255 (maximum) sera 255 au lieu d'être complété
Il semblait convertir la valeur de manière cyclique et la renvoyer.
(ex:256=0, 260=4)
C'est très horrible et j'aime celui-ci Le but n'est pas cette image, donc je vais l'améliorer.
Si vous le recherchez, vous pouvez utiliser cv2.add ()
Il semble que les valeurs supérieures à 255 soient traitées comme 255.
J'ai essayé.
Ajoutez votre propre valeur de pixel à vous-même = temps constants Parce que ça veut dire La fonction de conversion est la suivante.
Fonction de conversion
def toneCurve11(frame, n = 1):
tmp = frame
if n > 1:
for i in range(1,n):
tmp = cv2.add(tmp, frame)
return tmp
frame
est un tableau de valeurs de pixels
«n» représente le nombre de fois que la valeur du pixel est multipliée, c'est-à-dire le nombre de fois à ajouter.
Ensuite, c'est le résultat.
L'image originale | Image convertie |
---|---|
Oui, c'est ce que je cherchais! Il produit une image avec un contraste accru. (L'image en échelle de gris était-elle meilleure?)
Cependant, comment pouvons-nous obtenir la conversion illustrée à la figure 2 en ajoutant simplement cette méthode? Voulez-vous produire une image?
** J'ai trouvé un coup rapide **: feux d'artifice:
Voici ce que j'ai trouvé.
** Inversion négative / positive
>cv2.add ()
> Inversion négative / positive
**
Cela ressemble à ceci sur la figure.
1.Pas de conversion | 2.Inversion négative / positive |
3.cv2.add()Doublé avec | 4.Inversion négative / positive |
Les changements sont de l'ordre de 1, 2, 3, 4.
Le code de conversion est le suivant.
Fonction de conversion
def negaPosi(frame):
return 255 - frame
def toneCurve21(frame, n = 1):
if n > 1:
return negaPoso(toneCurve11(negaPosi(frame), n))
return frame
Comme avant
frame
est un tableau de valeurs de pixels
«n» représente le nombre de fois que la valeur du pixel est multipliée, c'est-à-dire le nombre de fois à ajouter.
Eh bien, le résultat.
L'image originale | Image convertie |
---|---|
L'image avec le contraste réduit a été produite en toute sécurité.
Même si je fais ce qui précède, cela fonctionne bien. J'avais l'impression d'être interrogé sur la ** commande **, alors j'ai décidé de me pencher sur d'autres méthodes.
Ensuite, cv2 semble avoir une chose pratique appelée ** LUT (Look Up Table)
**.
De plus, si la commande peut être faite assez petite ...
LUT J'ai pris quelques approches ci-dessus, mais à la fin Si vous remplacez la valeur de pixel acquise par une autre valeur de pixel, vous pouvez la convertir.
Ici, les valeurs possibles des valeurs de pixel sont ** au plus 256 voies ** de 0 à 255. Si tel est le cas, ayez une table de correspondance dans laquelle la valeur de destination de conversion pour une certaine valeur de pixel est enregistrée à l'avance. Lorsque vous faites référence à une valeur de pixel, au lieu de calculer la valeur de pixel elle-même Les coûts de calcul peuvent être réduits en les remplaçant simplement.
Voici une brève description de la LUT.
Par exemple, la table de correspondance suivante peut être considérée.
Pixel de référence | Changer de destination | |
---|---|---|
0 | -> | 0 |
1 | -> | 2 |
... | ... | |
127 | -> | 254 |
128 | -> | 255 |
... | ... | |
255 | -> | 255 |
Oui, ce tableau est le tableau de correspondance de la courbe de tonalité de la figure 1.
Si la valeur de pixel de l'image [90] [90] est Si c'était «[12, 245, 98]» Après avoir appliqué LUT Il devient «[24, 255, 196]».
Nous utiliserons en fait la LUT.
Fonction de conversion
def toneCurve12(frame, n = 1):
look_up_table = np.zeros((256,1), dtype = 'uint8')
for i in range(256):
if i < 256 / n:
look_up_table[i][0] = i * n
else:
look_up_table[i][0] = 255
return cv2.LUT(frame, look_up_table)
frame
est un tableau de valeurs de pixels
«n» indique combien de fois la valeur du pixel doit être multipliée.
look_up_table = np.zeros((256,1), dtype = 'uint8')
Pour la partie de, créez une table de correspondance (256 x 1) pour la conversion.
À ce stade, les valeurs suivantes sont toujours stockées.
>>> look_up_table = np.zeros((256,1), dtype = 'uint8')
>>> look_up_table
array([[0],
[0],
[0],
...,
[0],
[0]], dtype=uint8)
>>> len(look_up_table)
256
À partir de la ligne suivante, nous stockerons les valeurs à référencer dans ce tableau.
for i in range(256):
if i < 256 / n:
look_up_table[i][0] = i * n
else:
look_up_table[i][0] = 255
En ce qui concerne la partie de, enregistrez la valeur de pixel dans la table de correspondance pour la conversion créée précédemment.
Aussi
if i < 256 / n:
La partie de est une généralisation de l'expression conditionnelle afin qu'elle fonctionne même si la valeur du pixel est n fois. (ex: n = 3 [3 fois la valeur du pixel])
return cv2.LUT(frame, look_up_table)
En ce qui concerne la partie de, la correspondance est prise par la LUT enregistrée plus tôt, Renvoie les données d'image converties.
Eh bien, le résultat.
L'image originale | Amélioration 1 | Amélioration 2 |
---|---|---|
Vous pouvez obtenir l'image souhaitée.
Jetons un coup d'œil au temps d'exécution (ms).
n = 2 | n = 3 | n = 4 | |
---|---|---|---|
Amélioration 1 | 4.9848556 | 9.9725723 | 15.921831 |
Amélioration 2 | 4.9870014 | 4.9834251 | 4.9870014 |
Le traitement est plus rapide.
De la même manière, nous améliorerons la figure 2.
Fonction de conversion
def toneCurve22(frame, n = 1):
look_up_table = np.zeros((256,1), dtype = 'uint8')
for i in range(256):
if i < 256 - 256 / n :
look_up_table[i][0] = 0
else:
look_up_table[i][0] = i * n - 255 * (n - 1)
return cv2.LUT(frame, look_up_table)
Ce que je fais est presque le même, donc je ne vais pas l'expliquer en détail
if i < 256 - 256 / n :
La partie de est une généralisation de la partie fonction lorsque n = 2
où x <128
.
Si n = 2
x <256 --256 / n = 128
Autrement dit,
Il peut être transformé en «x <128».
Eh bien, le résultat.
L'image originale | Amélioration 1 | Amélioration 2 |
---|---|---|
Vous pouvez obtenir l'image souhaitée.
Jetons un coup d'œil au temps d'exécution (ms).
n = 2 | n = 3 | n = 4 | |
---|---|---|---|
Amélioration 1 | 25.915145 | 32.911539 | 36.406755 |
Amélioration 2 | 4.9862861 | 4.9872398 | 4.9846172 |
Après tout, celui qui traite rapidement est bon.
Cette fois, j'ai parlé de la courbe des tons.
OpenCV est très pratique. Mes ancêtres ne s'énervent pas ... De plus, Python peut être utilisé avec une seule commande.
Quelqu'un verra-t-il cet article? Ou, même si je suis inquiet S'il s'agit d'un mémorandum, assurez-vous Je poste toujours.
J'espère que cet article sera utile à quelqu'un un jour.
Enfin, mettez le code source utilisé cette fois et terminez. Que devrais-je faire ensuite?
Puis: vague:
Sous le répertoire courant Dans un répertoire appelé image Il existe un fichier image appelé castle.jpg. Si vous utilisez ce code, veuillez le modifier vous-même.
Installez également la bibliothèque ci-dessous.
console
$ pip install opencv-python
$ pip freeze
numpy==1.18.4
opencv-python==4.2.0.34
ex.py
import cv2
import numpy as np
def toneCurve(frame):
return 2 * frame
def negaPosi(frame):
return 255 - frame
def toneCurve11(frame, n = 1):
tmp = frame
if n > 1:
for i in range(1, n):
tmp = cv2.add(tmp, frame)
return tmp
def toneCurve12(frame, n = 1):
look_up_table = np.zeros((256, 1), dtype = 'uint8')
for i in range(256):
if i < 256 / n:
look_up_table[i][0] = i * n
else:
look_up_table[i][0] = 255
return cv2.LUT(frame, look_up_table)
def toneCurve21(frame, n = 1):
if n > 1:
return negaPoso(toneCurve11(negaPosi(frame), n))
return frame
def toneCurve22(frame, n = 1):
look_up_table = np.zeros((256, 1), dtype = 'uint8')
for i in range(256):
if i < 256 - 256 / n :
look_up_table[i][0] = 0
else:
look_up_table[i][0] = i * n - 255 * (n - 1)
return cv2.LUT(frame, look_up_table)
def main():
img_path = '.\\image\\castle.jpg'
img = cv2.imread(img_path)
cv2.imwrite('.\\image\\tone00.jpg', toneCurve(img))
cv2.imwrite('.\\image\\tone11.jpg', toneCurve11(img, 2))
cv2.imwrite('.\\image\\tone12.jpg', toneCurve12(img, 2))
cv2.imwrite('.\\image\\tone21.jpg', toneCurve21(img, 2))
cv2.imwrite('.\\image\\tone22.jpg', toneCurve22(img, 2))
if __name__ == '__main__':
main()
[^ 1]: Extrait de [Computer Graphics] cv
Recommended Posts