firelab-general/size_projection.py

76 lines
2.0 KiB
Python

# use headless backend
import matplotlib
matplotlib.use("Agg")
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(image=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])