Point Polygon Test
Table of Contents
Prev Tutorial: Image Moments
Next Tutorial: Image Segmentation with Distance Transform and Watershed Algorithm
Original author | Ana Huamán |
Compatibility | OpenCV >= 3.0 |
Goal
In this tutorial you will learn how to:
- Use the OpenCV function cv::pointPolygonTest
Theory
Code
C++
This tutorial code's is shown lines below. You can also download it from here
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( void )
{
const int r = 100;
vector<Point2f> vert(6);
vert[1] = Point( 1*r, 2*r );
vert[4] = Point( 3*r, 2*r );
for( int i = 0; i < 6; i++ )
{
line( src, vert[i], vert[(i+1)%6], Scalar( 255 ), 3 );
}
vector<vector<Point> > contours;
findContours( src, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);
{
{
raw_dist.at<float>(i,j) = (float)pointPolygonTest( contours[0], Point2f((float)j, (float)i), true );
}
}
double minVal, maxVal;
Point maxDistPt; // inscribed circle center
minMaxLoc(raw_dist, &minVal, &maxVal, NULL, &maxDistPt);
minVal = abs(minVal);
maxVal = abs(maxVal);
{
{
if( raw_dist.at<float>(i,j) < 0 )
{
}
else if( raw_dist.at<float>(i,j) > 0 )
{
}
else
{
}
}
}
imshow( "Source", src );
imshow( "Distance and inscribed circle", drawing );
waitKey();
return 0;
}
int rows
the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
Definition: mat.hpp:2137
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
"black box" representation of the file storage associated with a file on disk.
Definition: core.hpp:106
STL namespace.
Java
This tutorial code's is shown lines below. You can also download it from here
import java.util.ArrayList;
import java.util.List;
import org.opencv.core.Core;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.highgui.HighGui;
import org.opencv.imgproc.Imgproc;
class PointPolygonTest {
public void run() {
int r = 100;
Mat src = Mat.zeros(new Size(4 * r, 4 * r), CvType.CV_8U);
List<Point> vert = new ArrayList<>(6);
vert.add(new Point(3 * r / 2, 1.34 * r));
vert.add(new Point(1 * r, 2 * r));
vert.add(new Point(3 * r / 2, 2.866 * r));
vert.add(new Point(5 * r / 2, 2.866 * r));
vert.add(new Point(3 * r, 2 * r));
vert.add(new Point(5 * r / 2, 1.34 * r));
for (int i = 0; i < 6; i++) {
Imgproc.line(src, vert.get(i), vert.get((i + 1) % 6), new Scalar(255), 3);
}
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Imgproc.findContours(src, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
Mat rawDist = new Mat(src.size(), CvType.CV_32F);
float[] rawDistData = new float[(int) (rawDist.total() * rawDist.channels())];
for (int i = 0; i < src.rows(); i++) {
for (int j = 0; j < src.cols(); j++) {
rawDistData[i * src.cols() + j] = (float) Imgproc
.pointPolygonTest(new MatOfPoint2f(contours.get(0).toArray()), new Point(j, i), true);
}
}
rawDist.put(0, 0, rawDistData);
MinMaxLocResult res = Core.minMaxLoc(rawDist);
double minVal = Math.abs(res.minVal);
double maxVal = Math.abs(res.maxVal);
Mat drawing = Mat.zeros(src.size(), CvType.CV_8UC3);
byte[] drawingData = new byte[(int) (drawing.total() * drawing.channels())];
for (int i = 0; i < src.rows(); i++) {
for (int j = 0; j < src.cols(); j++) {
if (rawDistData[i * src.cols() + j] < 0) {
drawingData[(i * src.cols() + j) * 3] =
(byte) (255 - Math.abs(rawDistData[i * src.cols() + j]) * 255 / minVal);
} else if (rawDistData[i * src.cols() + j] > 0) {
drawingData[(i * src.cols() + j) * 3 + 2] =
(byte) (255 - rawDistData[i * src.cols() + j] * 255 / maxVal);
} else {
drawingData[(i * src.cols() + j) * 3] = (byte) 255;
drawingData[(i * src.cols() + j) * 3 + 1] = (byte) 255;
drawingData[(i * src.cols() + j) * 3 + 2] = (byte) 255;
}
}
}
drawing.put(0, 0, drawingData);
HighGui.imshow("Source", src);
HighGui.imshow("Distance and inscribed circle", drawing);
HighGui.waitKey();
System.exit(0);
}
}
public class PointPolygonTestDemo {
public static void main(String[] args) {
// Load the native OpenCV library
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
new PointPolygonTest().run();
}
}
Python
This tutorial code's is shown lines below. You can also download it from here
from __future__ import print_function
from __future__ import division
import cv2 as cv
import numpy as np
# Create an image
r = 100
src = np.zeros((4*r, 4*r), dtype=np.uint8)
# Create a sequence of points to make a contour
vert = [None]*6
vert[0] = (3*r//2, int(1.34*r))
vert[1] = (1*r, 2*r)
vert[2] = (3*r//2, int(2.866*r))
vert[3] = (5*r//2, int(2.866*r))
vert[4] = (3*r, 2*r)
vert[5] = (5*r//2, int(1.34*r))
# Draw it in src
for i in range(6):
cv.line(src, vert[i], vert[(i+1)%6], ( 255 ), 3)
# Get the contours
contours, _ = cv.findContours(src, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# Calculate the distances to the contour
raw_dist = np.empty(src.shape, dtype=np.float32)
for i in range(src.shape[0]):
for j in range(src.shape[1]):
raw_dist[i,j] = cv.pointPolygonTest(contours[0], (j,i), True)
minVal, maxVal, _, maxDistPt = cv.minMaxLoc(raw_dist)
minVal = abs(minVal)
maxVal = abs(maxVal)
# Depicting the distances graphically
drawing = np.zeros((src.shape[0], src.shape[1], 3), dtype=np.uint8)
for i in range(src.shape[0]):
for j in range(src.shape[1]):
if raw_dist[i,j] < 0:
drawing[i,j,0] = 255 - abs(raw_dist[i,j]) * 255 / minVal
elif raw_dist[i,j] > 0:
drawing[i,j,2] = 255 - raw_dist[i,j] * 255 / maxVal
else:
drawing[i,j,0] = 255
drawing[i,j,1] = 255
drawing[i,j,2] = 255
cv.circle(drawing,maxDistPt, int(maxVal),(255,255,255), 1, cv.LINE_8, 0)
cv.imshow('Source', src)
cv.imshow('Distance and inscribed circle', drawing)
void minMaxLoc(InputArray src, double *minVal, double *maxVal=0, Point *minLoc=0, Point *maxLoc=0, InputArray mask=noArray())
Finds the global minimum and maximum in an array.
void line(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
Draws a line segment connecting two points.
void circle(InputOutputArray img, Point center, int radius, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
Draws a circle.
double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist)
Performs a point-in-contour test.
void findContours(InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())
Finds contours in a binary image.
Explanation
Result
Here it is: