I have a contour below. As I wanted to extract all the pixels inside this contour and black out everything else to remove noise, I used cv2.pointPolygonTest for the purpose.
Below are the code I used to attempt to create the mask.
inside_or_not = np.zeros(img.shape[:2],dtype = np.int32)
for i in range(0,img.shape[0]):
for j in range(0,img.shape[1]):
inside_or_not[i,j] = cv2.pointPolygonTest(body_line,(i,j),False)
Only 2 points were found to be inside the point. On top of that, I expect the number of points lying on the contour, hence returning 0 from the cv2.pointPolygonTest should match the number of pixels defining the contour. However when I run sum(sum(inside_or_not == 0)), it does not match the No. of pixels on the contour.
I also used mouse click to click a point obviously inside the contour and put that point into the test; but -1 is returned indicating the test failed.
I also used a approxPolyDP function to attempt to approximate the contour with less vertices. This time a bit more points were returned. However I have no idea why!
Any help is appreciated, thanks.
Since you have a well defined contour, you can simply use findContour
with CV_RETR_EXTERNAL
to detect the external contour, and draw the region inside it with drawContour(..., CV_FILLED)
. Once you have the mask, you can use copyTo
to copy only the parts of your original image according to the mask.
Here an example, it's C++, but the porting to python is straightforward.
#include <opencv2\opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
// Load image
Mat3b img = imread("path_to_image_shape");
// Just to have a background image the same size of your image.
Mat3b bkg = imread("path_to_image_background");
resize(bkg, bkg, img.size());
// Convert to gray
Mat1b gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
// Get external contour
vector<vector<Point>> contours;
findContours(gray.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
// contours has size 1 here, you need to check this in a real application
// Create a mask with the inner part of the contour
Mat1b mask(img.size(), uchar(0));
drawContours(mask, contours, 0, Scalar(255), CV_FILLED);
// Create a black RGB image
Mat3b res(img.size(), Vec3b(0,0,0));
// Copy the image according to the mask
bkg.copyTo(res, mask);
imshow("result", res);
waitKey();
return 0;
}