I want to find the maximum inscribing circle of contour.
I have detected the contour with cv::findContours
and it is there as a vector<Point>
.
I know how to detect the minimum enclosing circle ( cv::minEnclosingCircle
), but not how to get the maximum inclosing circle. How to do this?
Question2: How do i get the inscribing and circumscribing circles centered on the center of mass?
For clarification, i try to describe, what i mean with these circels:
You can:
1) create a mask from your contour
2) Compute the distanceTransform
on the mask
3) The highest value is the radius, its position is the center
Code:
#include <opencv2\opencv.hpp>
int main()
{
// Load image
cv::Mat1b img = cv::imread("path_to_img", cv::IMREAD_GRAYSCALE);
// Correct image
cv::Mat1b bin = img < 127;
// Find contour
std::vector<std::vector<cv::Point>> contours;
cv::findContours(bin, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
// Draw on mask
cv::Mat1b mask(bin.rows, bin.cols, uchar(0));
cv::drawContours(mask, contours, 0, cv::Scalar(255), cv::FILLED);
// Distance Trasnsform
cv::Mat1f dt;
cv::distanceTransform(mask, dt, cv::DIST_L2, 5, cv::DIST_LABEL_PIXEL);
// Find max value
double max_val;
cv::Point max_loc;
cv::minMaxLoc(dt, nullptr, &max_val, nullptr, &max_loc);
// Output image
cv::Mat3b out;
cv::cvtColor(img, out, cv::COLOR_GRAY2BGR);
cv::circle(out, max_loc, max_val, cv::Scalar(0, 255, 0));
return 0;
}
At least i solved the calculation of the two circles with the center on the center of mass (in a way similar to @Grillteller suggested):
Point2f p_Contour_first = vp_Contour[0];
double circumCirc_Radius = norm(p_Centroid - p_Contour_first);
double inscriCirc_Radius = norm(p_Centroid - p_Contour_first);
for(int p = 0; p < vp_Contour.size(); p++)
{
Point2f p_Contour_current = vp_Contour[p];
double r = norm(p_Centroid - p_Contour_current);
if(r < inscriCirc_Radius) inscriCirc_Radius = r;
if(r > circumCirc_Radius) circumCirc_Radius = r;
}
But the original question remeains (max area, center pos doesn't matter).
@Miki's answer is great and extremely useful, I just spent a bit of time translating it into python, thought I should leave it here as well
#get maximum inscribed circle
#my input image is called "frame"
#get threshold image from frame
ret, thresh = cv2.threshold(frame, 100, 255, cv2.THRESH_BINARY)
contours,hierarchy = cv2.findContours(thresh, 1, cv2.CHAIN_APPROX_NONE)
#create blank mask
mask = np.zeros(frame.shape[:2], dtype="uint8")
cv2.drawContours(mask, contours, -1, 255, -1)
dist = cv2.distanceTransform(mask, cv2.DIST_L2, 0)
NULL,max_val,NULL,max_indx=cv2.minMaxLoc(dist)
(x,y),radius = max_indx, max_val
#draw circle on original image
cv2.circle(frame, (x,y), radius, (0,255,0), 2)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.