firelab-general/size_projection.py

72 lines
1.9 KiB
Python

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])