Dice detecting OpenCV DBSCAN

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()

How about detecting the square faces (using edge detection) and using that to crop the image twice into the two areas of interest

Thanks James, I will try this. I’m not sure it will be able to detect the edges tho. What do you mean exactly by cropping it?

I am very sure that if not, some other Python library will.

What do you mean exactly by cropping it?

If this isn’t a learning project and you want a practical solution, maybe just get a plastic tray or put in dividers so the dice aren’t next to each other? (I’m always looking for the laziest fix, but this might not be applicable to your situation.)

1 Like

So i’ve tried the edge detection, but no luck yet. I guess because they’re both white and the shadow in between them is so minimal.
It is indeed a project, so I can’t have the easy fix unfortunately.
I also have to use OpenCV.
Any ogher suggestions by any chance?

Edge detect the spots and count them?