Ask Your Question
1

pointPolygonTest() throws error for some reason

asked 2019-01-11 04:17:13 -0600

Raki gravatar image

updated 2019-01-11 04:30:04 -0600

I am using the following piece of code to check if a point is inside the contour or not:

    # form the contour from points 
    cnt = []
    for pose in component.part_outline.outline_poses.poses:
                    point = (pose.position.x, pose.position.y)
                    cnt.append(point)    
    cnt = np.array(cnt)

    # get the point to be tested
    point = (screw.pose.position.x, screw.pose.position.y)

    # run the test
    is_inside = cv2.pointPolygonTest(cnt,point, False) 
    if is_inside > 0:
             print("bla bla") # act upon the outcome

and I get the following error for some reason:

"error: OpenCV(3.4.4) /io/opencv/modules/imgproc/src/geometry.cpp:103: error: (-215:Assertion failed) total >= 0 && (depth == CV_32S || depth == CV_32F) in function 'pointPolygonTest'\n\n"

This error message does not tell much to be honest, and I have absolutely no idea why this is happening. I checked the image, it's there. The contour and the point are also there, nothing is null or whatsoever.

P.S: In case if it helps, I tried to print the variable is_inside and it prints (-1.0) for 4 times, then the error is thrown.

Any idea?

edit retag flag offensive close merge delete

Comments

2

Looks like it needs integer or 32 bits floating point data. Check the type of pose.position.x and the type of screw.pose.position.x.

There is also a tutorial code here.

Eduardo gravatar imageEduardo ( 2019-01-11 04:37:47 -0600 )edit
1

(466, 43) (102, 37) (682, 458) (468, 459) (466, 43)

these are the points that I feed into, what's wrong with these anyway?

Raki gravatar imageRaki ( 2019-01-11 05:08:39 -0600 )edit
1

Okay, turns out one has to use int() to cast each value, as you said. I can accept your answer if you add it.

Raki gravatar imageRaki ( 2019-01-11 06:56:46 -0600 )edit

@Raki. Does your is working or not?

supra56 gravatar imagesupra56 ( 2019-01-11 15:50:38 -0600 )edit
1

@supra56 Mine works now yes.

Raki gravatar imageRaki ( 2019-01-14 00:58:52 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
5

answered 2019-01-11 13:45:12 -0600

Eduardo gravatar image

updated 2019-01-11 13:55:57 -0600

This is how to "decipher" your OpenCV assert error:

  • here https://docs.opencv.org/ you can access the OpenCV documentation
  • from the documentation you can have the C++ signature: double cv::pointPolygonTest (InputArray contour, Point2f pt, bool measureDist)
  • this is the Python signature: retval = cv.pointPolygonTest(contour, pt, measureDist) but since Python OpenCV interface is wrapped from C++, it is important to understand the C++ API
  • InputArray is just a proxy class, the most common OpenCV class is cv::Mat to hold image data or matrix information
  • (depth == CV_32S || depth == CV_32F) means that the expected depth of the input data should be CV_32S (32-bit integer) or CV_32F (32-bit floating point)

Here the mapping:

  • CV_8U <--> 8-bit unsigned integers (unsigned char in C++, uchar in OpenCV)
  • CV_8S <--> 8-bit signed integers (char in C++, schar in OpenCV)
  • CV_16U <--> 16-bit unsigned integers (unsigned short in C++, ushort in OpenCV)
  • CV_16S <--> 16-bit signed integers (short in C++)
  • CV_32S <--> 32-bit signed integesr (int in C++)
  • CV_32F <--> 32-bit floating-point numbers (float in C++)
  • CV_64F <--> 64-bit floating-point numbers (double in C++)

The list of primitive types in OpenCV:

//! - schar  - signed 1 byte integer
//! - uchar  - unsigned 1 byte integer
//! - short  - signed 2 byte integer
//! - ushort - unsigned 2 byte integer
//! - int    - signed 4 byte integer
//! - uint   - unsigned 4 byte integer
//! - int64  - signed 8 byte integer
//! - uint64 - unsigned 8 byte integer

For cv::Mat, the important things to remember for cv::Mat m; are:

Returns the depth of a matrix element.

The method returns the identifier of the matrix element depth (the type of each individual channel). For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of matrix types contains the following values:

CV_8U - 8-bit unsigned integers ( 0..255 )
CV_8S - 8-bit signed integers ( -128..127 )
CV_16U - 16-bit unsigned integers ( 0..65535 )
CV_16S - 16-bit signed integers ( -32768..32767 )
CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
  • number of channels of a mat m.channels(), e.g. 3 for a color image
  • type of a mat m.type(), that is the combination depth with channels, e.g. CV_8UC3 for a color image

This condition total >= 0 should mean that the number of points in the contour matrix must be >= 0. This looks a little bit odd since we could expect to check for a strictly positive number but this is just like it is written currently in the code:

double cv::pointPolygonTest( InputArray _contour, Point2f pt, bool measureDist )
{
    CV_INSTRUMENT_REGION();

    double result = 0;
    Mat contour = _contour.getMat();
    int i, total = contour.checkVector(2), counter = 0;
    int depth = contour.depth();
    CV_Assert( total >= 0 && (depth == CV_32S || depth == CV_32F));

    bool is_float = depth == CV_32F;
    double min_dist_num = FLT_MAX, min_dist_denom = 1;
    Point ip(cvRound(pt.x), cvRound(pt.y));

    if( total == 0 )
return measureDist ? -DBL_MAX : -1;

Also, don't be afraid to look ... (more)

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2019-01-11 04:17:13 -0600

Seen: 5,443 times

Last updated: Jan 11 '19