Reputation: 78
I have an RGB image.Suppose say I have two circles in it.I want to know which one is filled and which one is not.I followed the following steps: -imported the image as Bitmap
-converted into grayscale and used CannyEdgeDetector filter to find the edges. I get the following image
circle containing the letter "D" gives two edges, where as I need only one circle edge. Secondly, how do I find out which circle is filled and which one is not.
Upvotes: 2
Views: 1073
Reputation: 2260
Perform blob detection, with a pixel count
or even simpler count the black pixels
or even simpler and faster, take middle line and count how often it switches from white to black
Upvotes: 0
Reputation: 50682
For the MCQ answers sheet, it might be easier to go by positions of the circles.
Just compare stock images of the clear, circled A, B, C and D's to the scanned images and see which differ the most. A simple darkness summation might be enough.
Also: Comparing the circles against each other might be useful too to compensate for a bad/dark/light scan or smudgy paper.
For special cases if the test isn't absolutely sure I'd probably pass it to a human being for further investigation. E.g., when you allow students to undo an answer by circling their second guess or when a student decides to make a real mess by using a bad eraser.
Final tip: make sure you do not accept answers that have the correct circle filled; make sure the other circles are clear at the same time so students can't cheat by filling all circles. (Some professors use a paper mask that overlays all bad answers so they can quickly spot unmarked correct answers. But if the student just marks all answers this fails big time.)
Upvotes: 3
Reputation: 5369
I would not know any "formal" algorithm matching your criteria. I would also doubt that you would find any.
When you say the circles are "darkened", this can be interpreted as this: "Many pixels (above a population threshold) would be black, or at least dark (above a colour threshold).". Based on known circle and radius, I would follow this approach (written in pseudocode but I suppose you get the meaning):
//define thresholds
colourThreshold=...
populationThreshold=...
centerPoint = getCircleCenter();
radius = getCircleRadius();
darkPixelsCount = 0;
for(x=centerPoint.X-radius;x<centerPoint.X+radius;x++){
for(y=centerPoint.Y-sqrt(abs(radius^2-(x - centerPoint.X)^2));centerPoint.Y+sqrt(abs(radius^2-(x - centerPoint.X)^2));y++){
if (image(x, y) > colourThreshold){
darkPixelsCounter++;
if(darkPixelsCounter > populationThreshold){
//If you reach this point, circle has been darkened
return;
}
}
}
}
//If you reach this point, circle has not been darkened
return;
I don't know if it is efficient, or if there is a more elegant way to do it. I suppose you could play with performance and accuracy by moderating the thresholds.
Hope I helped!
Upvotes: 2