Il existe de nombreuses possibilités d'utiliser l'extraction et la correspondance de points d'entités OpenCV. Lors de l'utilisation de plusieurs images, l'extraction des points caractéristiques prenait souvent du temps. Par conséquent, cette fois, j'ai créé un programme qui génère les informations sur les points caractéristiques dans un fichier et les utilise pour la correspondance.
Cette fois, à titre d'exemple, trouvons une fille aux lunettes rouges (image cible) parmi les filles (12 images source)!
Image source ⬇︎
Image cible ⬇︎
Cette fois, nous avons développé dans l'environnement suivant. OpenCV 4.1.2 Python 3.8.1
Voici le déroulement du programme. J'expliquerai étape par étape dans la section suivante.
Tout d'abord, save_features.py pour obtenir les informations sur les points caractéristiques de l'image source (filles) et les enregistrer dans un fichier.
Cette fois, j'ai utilisé AKAZE, un descripteur de point de fonction implémenté dans OpenCV.
Pour enregistrer le keypoint
en tant que fichier, vous devez accéder et lister le cv :: KeyPoint
.
save_features.py
#Liste des points clés
keypoint = []
for p in features[0]:
temp = (p.pt, p.size, p.angle, p.response, p.octave, p.class_id)
keypoint.append(temp)
De plus, cette fois, les informations sur les points caractéristiques ont été converties en octets afin de réduire la consommation de mémoire.
save_features.py
#Convertir le point-clé en octets
map(bytes, keypoints)
Voici le code source complet.
save_features.py
import cv2 as cv
import pickle
SOURCE_FILES = [
"youngwoman_37.jpg ",
"youngwoman_38.jpg ",
"youngwoman_39.jpg ",
"youngwoman_40.jpg ",
"youngwoman_41.jpg ",
"youngwoman_42.jpg ",
"youngwoman_43.jpg ",
"youngwoman_44.jpg ",
"youngwoman_45.jpg ",
"youngwoman_46.jpg ",
"youngwoman_47.jpg ",
"youngwoman_48.jpg ",
]
def get_features(img_file_name):
"""Get features of master images
Args:
img_file_name(list): Master image
Returns:
keypoints, descriptors, img
"""
img = cv.imread("images/" + img_file_name)
#Extraction d'informations sur les points caractéristiques
akaze = cv.AKAZE_create()
kp, des = akaze.detectAndCompute(img, None)
features = [kp, des]
return features
sources = {}
for item in SOURCE_FILES:
features = get_features(item)
#Liste des points clés
keypoints = []
for p in features[0]:
temp = (p.pt, p.size, p.angle, p.response, p.octave, p.class_id)
keypoints.append(temp)
#Convertir les points-clés en octets
map(bytes, keypoints)
#Les informations sur les points caractéristiques sont converties dans un dictionnaire
sources[item] = {
"src": item,
"keypoint": keypoints,
"descriptor": features[1],
}
#Écrire des informations sur les points caractéristiques dans un fichier
with open("sources_data.pickle", mode="wb") as f:
pickle.dump(sources, f)
Le traitement est effectué dans get_features_from_file.py à partir de l'étape 2. Comme pour l'image source, les informations sur les points caractéristiques sont acquises à l'aide d'AKAZE, qui est un descripteur de points caractéristiques.
get_features_from_file.py
#Charger l'image cible
target_img = cv.imread("images/target_girl.jpg ")
#Acquisition de fonctionnalités
akaze = cv.AKAZE_create()
target_keypoint, target_descriptor = akaze.detectAndCompute(target_img, None)
Obtenez des informations sur les points caractéristiques du fichier avec get_sources ()
.
Puisque keypoints
a été converti en octet afin de le rendre pickle, il est converti en liste et renvoyé à la structure d'origine.
get_features_from_file.py
def get_sources():
"""Get source's features from file
Returns:
sources(list): source's keypoints, descriptors,and img
"""
#Obtenir des informations sur les points caractéristiques d'un fichier
with open("sources_data.pickle", mode="rb") as f:
sources = pickle.load(f)
for n in sources:
items = sources[n]
#Changer les points-clés d'octets en liste
list(map(list, items["keypoint"]))
#Restaurer les points clés à la structure d'origine
keypoints = []
for p in items["keypoint"]:
temp = cv.KeyPoint(
x=p[0][0],
y=p[0][1],
_size=p[1],
_angle=p[2],
_response=p[3],
_octave=p[4],
_class_id=p[5],
)
keypoints.append(temp)
items["keypoint"] = keypoints
return sources
Correspond aux informations de point caractéristique de l'image cible pour chaque image source. Les données sont éclaircies et si le nombre de points caractéristiques correspondants est égal ou supérieur au seuil défini (défini sur 20 cette fois), la correspondance est réussie.
get_features_from_file.py
for n in sources:
source = sources[n]
source_img = cv.imread("images/" + source["src"])
matches = matcher.knnMatch(source["descriptor"], target_des, k=2)
#Affiner les données
ratio = 0.5
matched_keypoints = []
for m, n in matches:
if m.distance < ratio * n.distance:
matched_keypoints.append([m])
#Image de résultat de sortie lorsqu'il y a plus de bons que n'importe quel seuil
if len(matched_keypoints) > 20:
out = cv.drawMatchesKnn(
source_img,
source["keypoint"],
target_img,
target_kp,
matched_keypoints,
None,
flags=2,
)
Voici le code source complet.
get_features_from_file.py
import cv2 as cv
import pickle
def get_sources():
"""Get source's features from file
Returns:
sources(list): source's keypoints, descriptors,and img
"""
#Obtenir des informations sur les points caractéristiques d'un fichier
with open("sources_data.pickle", mode="rb") as f:
sources = pickle.load(f)
for n in sources:
items = sources[n]
#Changer les points-clés d'octets en liste
list(map(list, items["keypoint"]))
#Restaurer les points clés à la structure d'origine
keypoints = []
for p in items["keypoint"]:
temp = cv.KeyPoint(
x=p[0][0],
y=p[0][1],
_size=p[1],
_angle=p[2],
_response=p[3],
_octave=p[4],
_class_id=p[5],
)
keypoints.append(temp)
items["keypoint"] = keypoints
return sources
matcher = cv.BFMatcher()
#Charger l'image cible
target_img = cv.imread("images/target_girl.jpg ")
#Acquisition de fonctionnalités
akaze = cv.AKAZE_create()
target_kp, target_des = akaze.detectAndCompute(target_img, None)
#Lire les informations de point caractéristique de l'image source à partir du fichier
sources = get_sources()
for n in sources:
source = sources[n]
source_img = cv.imread("images/" + source["src"])
matches = matcher.knnMatch(source["descriptor"], target_des, k=2)
#Affiner les données
ratio = 0.5
matched_keypoints = []
for m, n in matches:
if m.distance < ratio * n.distance:
matched_keypoints.append([m])
#Image de résultat de sortie lorsqu'il y a plus de bons que n'importe quel seuil
if len(matched_keypoints) > 20:
out = cv.drawMatchesKnn(
source_img,
source["keypoint"],
target_img,
target_kp,
matched_keypoints,
None,
flags=2,
)
cv.imwrite("images/result.jpg ", out)
cv.waitKey()
Dans l'image de résultat ci-dessous, les points caractéristiques correspondant entre l'image source et l'image cible sont dessinés. J'ai pu trouver la fille cible en toute sécurité!
La clé pour enregistrer des points caractéristiques dans un fichier est
Accéder à cv :: KeyPoint
Faire une liste en fonction des informations consultées
est.
Si vous avez la possibilité de traiter des images avec OpenCV, veuillez l'essayer.
Exporter KeyPoint d'OpenCV pour Python 3 vers un fichier
[Correspondance des points de fonction avec python3, opencv3 (AKAZE, KNN)] (https://techtech-sorae.com/python3opencv3%E3%81%A7%E7%89%B9%E5%BE%B4%E7%82%B9%E3%83%9E%E3%83%83%E3%83%81%E3%83%B3%E3%82%B0akaze-knn/)
Recommended Posts