Ask Your Question

pointPolygonTest is not working properly

asked 2012-08-15 20:19:14 -0600

demon gravatar image

updated 2012-08-16 01:12:42 -0600

I used pointPolygonTest for finding the maximum radius of the inscribed circle in the shape. For the same figure, depending on the turn to 90-180-270 degrees obtained different results. Have any ideas? image description image description

# -*- coding: utf-8 -*-
import cv2
import as cv
import numpy as np

contours, hierarchy = cv2.findContours(image_bin.copy(),cv2.RETR_CCOMP , cv2.CHAIN_APPROX_SIMPLE)
image_with_contour=np.zeros(image.shape, np.uint8)
cv2.drawContours(image_with_contour,contours,-1,(255,255,255),1, cv2.CV_AA)

for ind_y in range(image.shape[0]):
    for ind_x in range(image.shape[1]):
        dist[ind_y,ind_x] = cv2.pointPolygonTest(contours[0],(ind_y,ind_x),True)

minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(dist),(maxLoc[1],maxLoc[0]),int(maxVal),cv.CV_RGB(0, 255, 0),1, cv.CV_AA,0)

cv2.imshow('original', image)
cv2.imshow('contour', image_with_contour)

edit retag flag offensive close merge delete


If the code is not too big, you may want to post it here.

sammy gravatar imagesammy ( 2012-08-16 00:59:48 -0600 )edit

code is not too big, but i use python

demon gravatar imagedemon ( 2012-08-16 01:06:26 -0600 )edit

2 answers

Sort by ยป oldest newest most voted

answered 2012-08-16 02:12:35 -0600

sammy gravatar image

updated 2012-08-16 02:14:04 -0600

I've tried to replicate your results, but it works fine for me. Here is the code (C++)

Note that I have padded the input image, in order to have the correct contour (findContours() splits the contour because it touches the image edges). It may that this is your problem.

Also, note the different parameters for findContours. With your flags, the correct contour is the second one (index 1, not 0) in my test. With my flags, the good one is the first (index 0).

image description

cv::Mat contourImg = imread("contour.png");
std::vector<cv::Mat> channels;
cv::split(contourImg, channels);

    // On these lines, the input image is padded
cv::Mat gray(contourImg.rows+20, contourImg.cols+20, CV_8UC1);
gray = 255;
channels[0].copyTo(gray(cv::Rect(10,10,contourImg.cols, contourImg.rows)));

cv::imshow("Original", gray);
std::vector<std::vector<cv::Point> > contours;
cv::findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE );
cv::Mat drawing(gray.size(), CV_8UC3);
cv::Mat draw2 = drawing.clone();

cv::drawContours(drawing, contours,0, cv::Scalar(20,175,20),1,CV_AA);

double dist, maxdist = -1;

cv::Point center;
for(int i = 0;i< contourImg.cols;i++)
    for(int j = 0;j< contourImg.rows;j++)

        dist = pointPolygonTest(contours[0], cv::Point(i,j),true);
        if(dist > maxdist)
            maxdist = dist;
            center = cv::Point(i,j);

cv::circle(drawing, center, maxdist, cv::Scalar(220,75,20),1,CV_AA);
cv::imshow("Contours", drawing);

return 0;
edit flag offensive delete link more


thanks for the answer, i am not yet try your code on c++.

before post a question, i tried to add padding to the image (in the image editor) - nothing changed.

i also tried different flags in findContours (i was looking for holes, but here i posted a simplified code), and external contour was in index 0.

i will try to do on C + + your example, but on Python I did it and it not help

demon gravatar imagedemon ( 2012-08-16 03:14:22 -0600 )edit

basicly, what is different is padding and flags. You should have the same results if you put them in your python code

sammy gravatar imagesammy ( 2012-08-16 03:19:35 -0600 )edit

in python with your flag and padding image the same result are not obtained

demon gravatar imagedemon ( 2012-08-16 03:40:17 -0600 )edit

what OpenCV version do you use? I have 2.4.2 It's a low chance to be a problem with the wrappers, looks like a bug in the function. Also, try to draw only the contour you are using as test

cv2.drawContours(image_with_contour,contours,0,(255,255,255),1, cv2.CV_AA)

To make sure you have the good one.

sammy gravatar imagesammy ( 2012-08-16 03:44:26 -0600 )edit

i tested on opencv 2.3.1, 2.4 and now tested on 2.4.2 - the result did not change. and i painted what contour i tested. maybe it's a bug.

demon gravatar imagedemon ( 2012-08-16 06:38:24 -0600 )edit

Did you check that you test for the correct contour? Use the contour index instead of -1 in the drawContours function. Also, check the correct data type for dist, and correct indexing when you populate dist

sammy gravatar imagesammy ( 2012-08-16 06:42:40 -0600 )edit

yeees, thank you very much. because the numpy horizontal and vertical index are reversed, i incorrectly calculated the distance in pointPolygonTest. Correct code: dist[ind_y,ind_x] = cv2.pointPolygonTest(contours[0],(ind_x,ind_y),True) and,maxLoc,int(maxVal),cv.CV_RGB(0, 255, 0),1, cv.CV_AA,0)

demon gravatar imagedemon ( 2012-08-16 07:25:04 -0600 )edit

Thank you very much. It saved my day!

Chandan gravatar imageChandan ( 2019-03-22 08:12:42 -0600 )edit

answered 2012-08-16 00:40:22 -0600

justin gravatar image

Do you test all the pixels of the Image or how do you try to find the maximum radius?

If you don't test all the pixels it might be a starting point problem (as you find the maximum for the upper part of the contour).

edit flag offensive delete link more


Yes, i test all pixels of the image and check inside or outside of contour, then choose maximum distance.

demon gravatar imagedemon ( 2012-08-16 00:48:08 -0600 )edit

Question Tools


Asked: 2012-08-15 20:19:14 -0600

Seen: 4,441 times

Last updated: Aug 16 '12