import base64 import cv2 as cv import numpy as np import matplotlib.pyplot as plt from skimage import measure, morphology, color, segmentation import io def get_projected_area(image, area_threshold, display_threshold): total_px = image.size total_mm = 60322.46 output = [] original = cv.imdecode(image, cv.IMREAD_UNCHANGED) original = cv.cvtColor(original, cv.COLOR_BGR2RGB) img = cv.cvtColor(original, cv.COLOR_BGR2GRAY) _retval, thresh_gray = cv.threshold(img, 200, 255, cv.THRESH_BINARY) img = morphology.area_closing(thresh_gray, area_threshold=area_threshold, connectivity=1) contours = measure.find_contours(array=img, level=100) fig, ax = plt.subplots() ax.imshow(original, cmap=plt.cm.gray, alpha=0.3) index = 1 for contour in contours: area = calculate_area(contour) if calculate_area(contour) > display_threshold: ax.plot(contour[:, 1], contour[:, 0], linewidth=0.5, color='orangered') cX, cY = center_of_mass(contour) plt.text(cY, cX, index, color='black', fontsize=6) output.append((index, round(area / total_px * total_mm, 2))) # print(area, total_px) index += 1 ax.axis('image') ax.set_xticks([]) ax.set_yticks([]) ax.margins(0) my_stringIObytes = io.BytesIO() plt.savefig(my_stringIObytes, format='png', dpi=500, bbox_inches='tight') my_stringIObytes.seek(0) image_arr = base64.b64encode(my_stringIObytes.read()).decode(encoding='utf-8') return image_arr, output def calculate_area(countour): c = np.expand_dims(countour.astype(np.float32), 1) c = cv.UMat(c) return cv.contourArea(c) def center_of_mass(X): x = X[:,0] y = X[:,1] g = (x[:-1]*y[1:] - x[1:]*y[:-1]) A = 0.5*g.sum() cx = ((x[:-1] + x[1:])*g).sum() cy = ((y[:-1] + y[1:])*g).sum() return 1./(6*A)*np.array([cx,cy])