OpenCV en Python. Partie 4

Bonjour, Habr! Dans cet article, je voudrais vous dire comment reconnaître des objets en utilisant uniquement OpenCV, en utilisant des cartes à jouer comme exemple:













introduction



Disons que nous avons l'image suivante avec des cartes:













Nous avons également des images de référence pour chaque carte:













Et maintenant, pour détecter chaque carte, nous devons écrire trois fonctions clés, qui:







  • trouve les contours de toutes les cartes;
  • trouve les coordonnées de chaque carte individuelle;
  • reconnaît la carte à l'aide de points clés.


Trouver les contours des cartes



def find_contours_of_cards(image):
    blurred = cv2.GaussianBlur(image, (3, 3), 0)
    T, thresh_img = cv2.threshold(blurred, 215, 255, 
                                  cv2.THRESH_BINARY)
    (_, cnts, _) = cv2.findContours(thresh_img, 
                                cv2.RETR_EXTERNAL,
                                cv2.CHAIN_APPROX_SIMPLE)
    return cnts
      
      





, , , . threshold() . , — , — , , . , , 215, 255, , 215, . . THRESH_BINARY(), , , 215 , . , — , , — - , :













, — , , . findContours(), , — , . cv2.RETR_EXTERNAL . , , cv2.RETR_LIST, . cv2.CHAIN_APPROX_SIMPLE, , , . , , , ? , . , cv2.CHAIN_APPROX_SIMPLE.









def find_coordinates_of_cards(cnts, image):
    cards_coordinates = {}
    for i in range(0, len(cnts)):
        x, y, w, h = cv2.boundingRect(cnts[i])
        if w > 20 and h > 30:
            img_crop = image[y - 15:y + h + 15,
                             x - 15:x + w + 15]
            cards_name = find_features(img_crop)
            cards_coordinates[cards_name] = (x - 15, 
                     y - 15, x + w + 15, y + h + 15)
    return cards_coordinates
      
      





, , . , , . , boundingRect() : x y , . , , , 31 , 4. , , .







, , , . find_features()( ), , . .









, . — . , . , , . , , - . , :













:













, . , . :







def find_features(img1):
    correct_matches_dct = {}
    directory = 'images/cards/sample/'
    for image in os.listdir(directory):
        img2 = cv2.imread(directory+image, 0)
        orb = cv2.ORB_create()
        kp1, des1 = orb.detectAndCompute(img1, None)
        kp2, des2 = orb.detectAndCompute(img2, None)
        bf = cv2.BFMatcher()
        matches = bf.knnMatch(des1, des2, k=2)
        correct_matches = []
        for m, n in matches:
            if m.distance < 0.75*n.distance:
                correct_matches.append([m])
                correct_matches_dct[image.split('.')[0]]
                    = len(correct_matches)
    correct_matches_dct =
        dict(sorted(correct_matches_dct.items(),
             key=lambda item: item[1], reverse=True))
    return list(correct_matches_dct.keys())[0]
      
      





ORB, ORB_create(), ( ) , . , , :













( ) . BFMatcher BFMatcher(). knnMatch() k , k 2. , . m.distance < 0.75*n.distance, . ( , ) , . :













Et puis dessinez un rectangle autour de la carte en utilisant la fonction draw_rectangle_aroud_cards ():







def draw_rectangle_aroud_cards(cards_coordinates, image):
    for key, value in cards_coordinates.items():
        rec = cv2.rectangle(image, (value[0], value[1]), 
                            (value[2], value[3]), 
                            (255, 255, 0), 2)
        cv2.putText(rec, key, (value[0], value[1] - 10), 
                    cv2.FONT_HERSHEY_SIMPLEX, 
                    0.5, (36, 255, 12), 1)
    cv2.imshow('Image', image)
    cv2.waitKey(0)
      
      





C'est tout. J'espère que c'était informatif) Le code et les images peuvent être trouvés sur github . Jusqu'à la prochaine fois :)








All Articles