Hi there,
I’m trying to make dice detection system using a Raspberry with a camera. I want to use the live video feed for this.
Now I’m able to detect the dice, but there is a slight problem.
Eventually there will be multiple dice rolled by a machine. This means it is possible that there will be dice right next to eachother.
The problem is that when I put 2 dice against eachother, the number on the dice will be calculated as if it was one dice. Now I’ve kinda fixed it by saying there cannot be more then 6 points in a cluster.
But now if I have a 2 on a dice and it’s against a 5 for example it still counts as 6. Now i’ve tried tweaking the eps value, but the distance between the 2 pips on a 2 dice roll are greater than one of the pips from the 2 next to another dice roll. I’ve added some pictures for you to see. Down here is the code
import cv2
import numpy as np
from picamera2 import Picamera2
from sklearn import cluster
# Setup van de camera
picam2 = Picamera2()
picam2.preview_configuration.main.size = (1920, 1080)
picam2.video_configuration.controls.FrameRate = 25
picam2.preview_configuration.main.format = "RGB888"
picam2.start()
params = cv2.SimpleBlobDetector_Params()
params.filterByInertia = True
params.minInertiaRatio = 0.6
detector = cv2.SimpleBlobDetector_create(params)
def get_blobs(frame):
frame_blurred = cv2.medianBlur(frame, 7)
frame_gray = cv2.cvtColor(frame_blurred, cv2.COLOR_BGR2GRAY)
blobs = detector.detect(frame_gray)
return blobs
def get_dice_from_blobs(blobs):
X = []
for b in blobs:
pos = b.pt
if pos!= None:
X.append(pos)
X = np.asarray(X)
if len(X) > 0:
clustering = cluster.DBSCAN(eps=60, min_samples=1).fit(X)
num_dice = max(clustering.labels_) + 1
dice = []
for i in range(num_dice):
X_dice = X[clustering.labels_ == i]
centroid_dice = np.mean(X_dice, axis=0)
dice.append([len(X_dice), *centroid_dice])
return dice
else:
return[]
def overlay_info(frame, dice, blobs):
for b in blobs:
pos = b.pt
r = b.size / 2
cv2.circle(frame, (int(pos[0]), int(pos[1])),
int(r), (255, 0, 0), 2)
for d in dice:
textsize = cv2.getTextSize(
str(d[0]), cv2.FONT_HERSHEY_PLAIN, 3, 2)[0]
cv2.putText(frame, str(d[0]),
(int(d[1] - textsize[0] / 2),
int(d[2] + textsize[1] / 2)),
cv2.FONT_HERSHEY_PLAIN, 3, (0, 255, 0), 2)
while True:
# Neem een afbeelding van de camera
frame = picam2.capture_array()
blobs = get_blobs(frame)
dice = get_dice_from_blobs(blobs)
out_frame = overlay_info (frame, dice, blobs)
cv2.imshow('frame', frame)
res = cv2.waitKey(1)
if res & 0xFF == ord('q'):
break
picam2.stop()
cv2.destroyAllWindows()