-
Notifications
You must be signed in to change notification settings - Fork 226
/
CardDetector.py
124 lines (93 loc) · 4.24 KB
/
CardDetector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
############## Python-OpenCV Playing Card Detector ###############
#
# Author: Evan Juras
# Date: 9/5/17
# Description: Python script to detect and identify playing cards
# from a PiCamera video feed.
#
# Import necessary packages
import cv2
import numpy as np
import time
import os
import Cards
import VideoStream
### ---- INITIALIZATION ---- ###
# Define constants and initialize variables
## Camera settings
IM_WIDTH = 1280
IM_HEIGHT = 720
FRAME_RATE = 10
## Initialize calculated frame rate because it's calculated AFTER the first time it's displayed
frame_rate_calc = 1
freq = cv2.getTickFrequency()
## Define font to use
font = cv2.FONT_HERSHEY_SIMPLEX
# Initialize camera object and video feed from the camera. The video stream is set up
# as a seperate thread that constantly grabs frames from the camera feed.
# See VideoStream.py for VideoStream class definition
## IF USING USB CAMERA INSTEAD OF PICAMERA,
## CHANGE THE THIRD ARGUMENT FROM 1 TO 2 IN THE FOLLOWING LINE:
videostream = VideoStream.VideoStream((IM_WIDTH,IM_HEIGHT),FRAME_RATE,1,0).start()
time.sleep(1) # Give the camera time to warm up
# Load the train rank and suit images
path = os.path.dirname(os.path.abspath(__file__))
train_ranks = Cards.load_ranks( path + '/Card_Imgs/')
train_suits = Cards.load_suits( path + '/Card_Imgs/')
### ---- MAIN LOOP ---- ###
# The main loop repeatedly grabs frames from the video stream
# and processes them to find and identify playing cards.
cam_quit = 0 # Loop control variable
# Begin capturing frames
while cam_quit == 0:
# Grab frame from video stream
image = videostream.read()
# Start timer (for calculating frame rate)
t1 = cv2.getTickCount()
# Pre-process camera image (gray, blur, and threshold it)
pre_proc = Cards.preprocess_image(image)
# Find and sort the contours of all cards in the image (query cards)
cnts_sort, cnt_is_card = Cards.find_cards(pre_proc)
# If there are no contours, do nothing
if len(cnts_sort) != 0:
# Initialize a new "cards" list to assign the card objects.
# k indexes the newly made array of cards.
cards = []
k = 0
# For each contour detected:
for i in range(len(cnts_sort)):
if (cnt_is_card[i] == 1):
# Create a card object from the contour and append it to the list of cards.
# preprocess_card function takes the card contour and contour and
# determines the cards properties (corner points, etc). It generates a
# flattened 200x300 image of the card, and isolates the card's
# suit and rank from the image.
cards.append(Cards.preprocess_card(cnts_sort[i],image))
# Find the best rank and suit match for the card.
cards[k].best_rank_match,cards[k].best_suit_match,cards[k].rank_diff,cards[k].suit_diff = Cards.match_card(cards[k],train_ranks,train_suits)
# Draw center point and match result on the image.
image = Cards.draw_results(image, cards[k])
k = k + 1
# Draw card contours on image (have to do contours all at once or
# they do not show up properly for some reason)
if (len(cards) != 0):
temp_cnts = []
for i in range(len(cards)):
temp_cnts.append(cards[i].contour)
cv2.drawContours(image,temp_cnts, -1, (255,0,0), 2)
# Draw framerate in the corner of the image. Framerate is calculated at the end of the main loop,
# so the first time this runs, framerate will be shown as 0.
cv2.putText(image,"FPS: "+str(int(frame_rate_calc)),(10,26),font,0.7,(255,0,255),2,cv2.LINE_AA)
# Finally, display the image with the identified cards!
cv2.imshow("Card Detector",image)
# Calculate framerate
t2 = cv2.getTickCount()
time1 = (t2-t1)/freq
frame_rate_calc = 1/time1
# Poll the keyboard. If 'q' is pressed, exit the main loop.
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
cam_quit = 1
# Close all windows and close the PiCamera video stream.
cv2.destroyAllWindows()
videostream.stop()