Tested with more advanced methods of card detection
This commit is contained in:
99
tools/feature_extraction.py
Normal file
99
tools/feature_extraction.py
Normal file
@@ -0,0 +1,99 @@
|
||||
import shenzhen_solitaire.card_detection.configuration as configuration
|
||||
from shenzhen_solitaire.board import NumberCard, SpecialCard
|
||||
|
||||
import cv2
|
||||
|
||||
import numpy as np
|
||||
from typing import Any, Tuple
|
||||
|
||||
|
||||
def prepare_image(image):
|
||||
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
||||
# edge_image = cv2.Canny(gray_image, 120, 160)
|
||||
ret, edge_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY_INV)
|
||||
contours2, hierarchy = cv2.findContours(
|
||||
edge_image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE
|
||||
)
|
||||
cnt2 = max(contours2, key=cv2.contourArea)
|
||||
|
||||
mask = np.zeros(edge_image.shape, dtype=edge_image.dtype)
|
||||
contim = cv2.drawContours(mask, [cnt2], 0, 1, cv2.FILLED)
|
||||
crop = np.multiply(edge_image, contim)
|
||||
return crop
|
||||
|
||||
|
||||
def match_template(image, template):
|
||||
image_cont, hierarchy = cv2.findContours(
|
||||
image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE
|
||||
)
|
||||
imcont = max(image_cont, key=cv2.contourArea)
|
||||
template_cont, hierarchy = cv2.findContours(
|
||||
template, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE
|
||||
)
|
||||
temcont = max(template_cont, key=cv2.contourArea)
|
||||
return [
|
||||
cv2.matchShapes(imcont, temcont, mode, 0.0)
|
||||
for mode in (
|
||||
cv2.CONTOURS_MATCH_I1,
|
||||
cv2.CONTOURS_MATCH_I2,
|
||||
cv2.CONTOURS_MATCH_I3,
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def type_fine(one, other) -> bool:
|
||||
if isinstance(one, SpecialCard):
|
||||
return one == other
|
||||
assert isinstance(one, NumberCard)
|
||||
if not isinstance(other, NumberCard):
|
||||
return False
|
||||
return one.number == other.number
|
||||
|
||||
|
||||
def debug_match(image, image_type, catalogue):
|
||||
img1 = prepare_image(image)
|
||||
i1_matches = []
|
||||
for index, (template_image, template_type) in enumerate(catalogue):
|
||||
img2 = prepare_image(template_image)
|
||||
i1_matches.append((template_type, match_template(img1, img2)[0], index))
|
||||
i1_matches = sorted(i1_matches, key=lambda x: x[1])
|
||||
if not type_fine(i1_matches[0][0], image_type):
|
||||
correct_index = 0
|
||||
for list_type, list_value, _ in i1_matches:
|
||||
if type_fine(list_type, image_type):
|
||||
correct_value = list_value
|
||||
break
|
||||
correct_index += 1
|
||||
print(
|
||||
f"{str(image_type):>20} matched as {str(i1_matches[0][0]):>20} {i1_matches[0][1]:.05f}, "
|
||||
f"correct in pos {correct_index:02d} val {correct_value:.05f}"
|
||||
)
|
||||
cv2.imshow("one", prepare_image(catalogue[i1_matches[0][2]][0]))
|
||||
cv2.imshow("two", img1)
|
||||
cv2.imshow("three", prepare_image(catalogue[i1_matches[correct_index][2]][0]))
|
||||
cv2.waitKey(0)
|
||||
return
|
||||
for list_type, list_value, list_index in i1_matches:
|
||||
if not type_fine(list_type, i1_matches[0][0]):
|
||||
if list_value * 0.6 < i1_matches[0][1]:
|
||||
print(
|
||||
f"{str(image_type):>20} {i1_matches[0][1]:.05f} very close"
|
||||
f" match with {str(list_type):>20} {list_value:.05f}"
|
||||
)
|
||||
return
|
||||
|
||||
if i1_matches[0][1] > 1:
|
||||
print(f"{image_type} with value {i1_matches[0][1]}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
pc = configuration.load("test_config.zip")
|
||||
laptop = configuration.load("laptop_conf.zip")
|
||||
bla = [(i, t) for i, t in pc.catalogue if t == SpecialCard.Hua]
|
||||
bla = pc.catalogue
|
||||
for pc_image, pc_card_type in bla:
|
||||
debug_match(pc_image, pc_card_type, laptop.catalogue)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user