Haar classifier trouble accurately detecting circles

Just continuing this thread since I had a limit on replies yesterday.
How does detectMultiScale really works, could this be the source of trouble, really?

Using a simple example, HAARs detected using default minNeighbor = 3 in detectMultiScale():
image

But reducing the minNeighbours to 0, you get all sorts of chaotic circles:
image

Hi,

I don’t know anything about this really, especially, I don’t know what Haar Classifier is.

I am just interested. Maybe it will help.

I made a .png file. It has 2 separate blue circles with no fill and 3 nested red circles with no fill on a white background.

This little bit of python correctly finds all the circles and draws around them in yellow:

#! /usr/bin/python3
# try out cv2

import cv2
import numpy as np
import os

def junkjpgs(path):
    print('Clearing out the folders we use, in case there is anything in there ... ')
    pics = os.listdir(path)
    if len(pics) == 0:
        print('Nothing in ' + path + '\n\n')
        return
    for file in pics:
        os.remove(path + file)
    print('ALL files removed from: ' + path + '\n\n')

junkjpgs(path2)

path1 = '/home/pedro/Pictures/'
path2 = '/home/pedro/OMRsteps/'

file = 'pic_find_circles.png'

# save the original image to compare with other steps in the process
pic = path1 + file
image = cv2.imread(pic)
name = 'original_image.png'
cv2.imwrite(path2 + name, image)

# it is better to get the edges from a blurred grey image apparently
grey = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
name = 'step1_grey.png'
cv2.imwrite(path2 + name, grey)

# blurring the image helps apparently
blurred = cv2.GaussianBlur(grey, (5, 5), 0)
name = 'step2_blurred.png'
cv2.imwrite(path2 + name, blurred)

# get the edges in the blurred image
edged = cv2.Canny(blurred, 75, 200)
name = 'step3_edged.png'
cv2.imwrite(path2 + name, edged)

# working on a copy is wise I read
edged2 = edged.copy()

# this only gets external contours
#contours, hierarchy = cv2.findContours(edged.copy(),cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# this gets nested contours, nested circles
contours, hierarchy = cv2.findContours(edged2, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
print('reading edged2, there are ', len(contours), ' contours')
# find contours in the edge map, then use the contours on the thresh
    
 # draw yellow strokes on the original image corresponding to the circles
# check that the contours line up with the circles on the image

paper2 = image.copy()

for b in range(0, len(contours)):
    cv2.drawContours(paper2, contours, b, (0, 230, 255), 4)

name = 'circle_the_contours.png'
cv2.imwrite(path2 + name, paper2)

Thanks for replying.
I suspect OpenCV’s support for HAAR classifier and the supporting functions is very poor. I tried loading the opencv_traincascade’s XML in python’s skimage module, that one simply hangs and returns nothing.
detectMultiScale() should only return detected rectangles/circles, but in this case, it also returns false circles that does not exist.
Although I’m not sure if they are scaled versions of the feature rectangle, which is why we want to hear from the experts :slight_smile:

when you give OpenCV ridiculous inputs, it’ll give you ridiculous results. it’s that simple.

algorithms aren’t fool-proof. they do exactly what you ask for. they can work well, if you use the right algorithm, and if you use it properly.

multiple people have been telling you that your approach is highly questionable. you’ve disregarded that advice.

the sample I posted with the circle picture. is just to understand how detectMultiScale really works.

But it shouldn’t behave that way, really!

This has been RESOLVED. there was a coding error in the INFO generation and that caused a lot of false detections.

So that is resolved for now.