Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect star shape in opencv-python

I need to detect the shapes and count the occurence of each shape in the image.I initially detected the contours and approximated them ,and counted the vertices in each of the contour present.My code looks like this:

import cv2
import numpy as np 
import collections
import sys

img = cv2.imread(str(sys.argv[1]),0)
ret,thresh = cv2.threshold(img,127,255,0)
contours,hierarchy = cv2.findContours(thresh,1,2)


no_of_vertices = []

i = 0
mask = np.zeros(img.shape,np.uint8)
for contour in contours:

 cnt = contour
 area = cv2.contourArea(cnt)
 if area>150:
    epsilon = 0.02*cv2.arcLength(cnt,True)
    approx = cv2.approxPolyDP(cnt,epsilon,True)
    no_of_vertices.append(len(approx))



counter = collections.Counter(no_of_vertices)




 a,b = counter.keys(),counter.values()

 i=0
 while i<len(counter):
   print a[i],b[i]
   i = i + 1

My code doesnt work for detecting the stars in this image:

Image with stars and other basic shapes

What changes should I make in the code?

like image 943
Kaushik Ramachandran Avatar asked Dec 10 '15 13:12

Kaushik Ramachandran


People also ask

How do you identify an OpenCV triangle?

Python - OpenCV & PyQT5 together To detect a triangle in an image, we first detect all the contours in the image. Then we loop over all the contours. Find the approximate contour for each of the contours. If the number of vertex points in the approximate contour is 3, then draw the contour and set it as a triangle.

What algorithm is used to detect polygons OpenCV?

Contours – convex contours and the Douglas-Peucker algorithm The first facility OpenCV offers to calculate the approximate bounding polygon of a shape is cv2. approxPolyDP. This function takes three parameters: A contour.


1 Answers

What worked for me was a comparison between the square root of the area over the perimeter of the shape. It's about 0.145 for a star (+/- .0015 because some of the edges didn't come out perfectly). 0.255 for the hexagon, .21 for the triangles, .247 for the square, and .250 for the pentagon.

Circularity also does work (which has the triangles come in at 0.26 to .27), and it differentiates similarly (.83 for the hexagon, .55-.56 for the triangle, .77 for the square, and .78 for the pentagon)

Below is the C++ code for it (I don't have python on my PC here, but the idea's the same):

#include "stdafx.h"
#include <opencv/cxcore.h>
#include <opencv2\core\mat.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <opencv/cxcore.h>
#include <opencv/highgui.h>
#include <opencv/cv.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>

using namespace cv;
using namespace std;

RNG rngee(12345);

int main() {
    Mat im = imread("C:/this/is.a/path/image.png", CV_LOAD_IMAGE_COLOR);
    Mat imgrey = im.clone();
    cvtColor(im, imgrey, CV_RGB2GRAY);
    vector<vector<Point> > imContours;
    vector<Vec4i> hierarchy;

    double divMaxSize = 0.175, divMinSize = 0.125;

   namedWindow("Image", CV_WINDOW_NORMAL| CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED);

   threshold(imgrey, imgrey, 100, 255, 0);

   findContours(imgrey, imContours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

    for (int i=0; i < imContours.size(); i++) {
         Scalar color = Scalar( rngee.uniform(0, 255), rngee.uniform(0,255), rngee.uniform(0,255) );
         cout << "sqrt(Area)/arcLength = " << sqrt(contourArea(imContours[i]))/arcLength(imContours[i], true ) << endl;
         if(sqrt(contourArea(imContours[i]))/arcLength(imContours[i], true ) < divMaxSize && sqrt(contourArea(imContours[i]))/arcLength( imContours[i], true ) > divMinSize) 
         {
             drawContours(im, imContours, i, color, 2, 8, hierarchy, 0, Point() ); 
             cout << "I'm a star!" << endl;
         }
        imshow("Image", im);
        waitKey(0);
    }
    imshow("Image", im);
    waitKey(0);

}

Both ways - either using circularity or my sqrt(area)/arclength method - result in: image with stars highlighted

like image 82
Rachel L Avatar answered Nov 15 '22 00:11

Rachel L