I am using opencv in python to try and detect shapes - in particular I want to be able to upload a picture of a wound - and for the system to find it. I think at the moment though its fixated on finding perfect circles.
input
output
current code looks like this
#/api/detect-shapes (comes back with the polygon shape data? comes back with modified images?)
@app.post("/api/detect-shapes")
async def post_detect_shapes(image_file: UploadFile = File(...)):
# The image contents are read using await image_file.read()
contents = await image_file.read()
# converted to a NumPy array using
nparr = np.fromstring(contents, np.uint8)
# decode the image data into a BGR image
img = cv.imdecode(nparr, cv.IMREAD_COLOR)
output = img.copy()
detected_polygons = extract_polygon_data(output)
for polygon in detected_polygons:
cv.polylines(output, [np.array(polygon)], True, (0, 255, 0), 2)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
gray = cv.medianBlur(gray, 5)
circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, 1, 20, param1=50, param2=20, minRadius=0, maxRadius=0)
detected_circles = np.uint16(np.around(circles))
for (x, y, r) in detected_circles[0, :] :
cv.circle(output, (x, y), r, (0, 255, 0), 3)
cv.circle(output, (x, y), 2, (0, 255, 255), 3)
#cv.imshow('output', output)
#cv.waitKey(0)
#cv.destroyAllWindows()
#Convert NumPy array (img) to PIL image
original_img_pil = Image.fromarray(cv.cvtColor(img, cv.COLOR_BGR2RGB))
#Convert PIL image to base64-encoded string
original_img_base64 = image_to_base64(original_img_pil)
#Convert NumPy array (output) to PIL image
output_img_pil = Image.fromarray(cv.cvtColor(output, cv.COLOR_BGR2RGB))
#Convert PIL image to base64-encoded string
output_img_base64 = image_to_base64(output_img_pil)
rn:int = random.randint(0, 100)
return {'original_img_base64': original_img_base64, 'output_img_base64': output_img_base64, "detected_polygon": detected_polygons}
should I try and detect by contours?
Hough line transform to find polygons in an image
void detect_by_contour()
{
//Following comments are written for non c++ programmers
auto img = cv::imread("../forum_quest/data/yd8pA.png");
if(img.empty()){
throw std::runtime_error("cannot open image");
}
cv::Mat gray_img;
cv::cvtColor(img, gray_img, CV_BGR2GRAY);
cv::Mat thin_img;
//make your lines as thin as possible
morphology_skeleton(gray_img, thin_img);
std::vector<std::vector<cv::Point>> contours;
cv::findContours(thin_img, contours, cv::RETR_EXTERNAL,
cv::CHAIN_APPROX_SIMPLE);
//remove contour if the area less than 100
auto it = std::remove_if(std::begin(contours), std::end(contours),
[](std::vector<cv::Point> const &a)
{
return cv::boundingRect(a).area() < 100;
});
//remove_if move unwanted elements to the backyard of the containers
//you need to call the erase function of the containers to remove
//unwanted elements
contours.erase(it, std::end(contours));
//contour_analyzer is a class used to print out statistic info
//of the contour
ocv::contour_analyzer analyzer;
//print_contour_attribute_name print out the attribute names
//of the contours as following
//CArea | BArea | Perimeter | Aspect | Extent | Solidity | PolySize
ocv::print_contour_attribute_name(std::cout);
for(size_t i = 0; i != contours.size(); ++i){
cv::drawContours(img, contours, static_cast<int>(i), {0,255,0}, 2);
std::cout<<analyzer.analyze(contours[i], 0.1);
cv::imshow("img", img);
cv::waitKey();
}
cv::imwrite("polygon.jpg", img);
}