|
|
import gradio as gr |
|
|
from PIL import Image |
|
|
import numpy as np |
|
|
from scipy.ndimage import label, find_objects |
|
|
|
|
|
|
|
|
def generate_mask(image): |
|
|
|
|
|
if isinstance(image, np.ndarray): |
|
|
image = Image.fromarray(image) |
|
|
|
|
|
|
|
|
image_rgb = image.convert("RGB") |
|
|
np_image = np.array(image_rgb) |
|
|
|
|
|
|
|
|
min_red, max_red = 21, 183 |
|
|
min_green, max_green = 0, 142 |
|
|
min_blue, max_blue = 0, 124 |
|
|
|
|
|
|
|
|
mask = ( |
|
|
(np_image[:, :, 0] >= min_red) & (np_image[:, :, 0] <= max_red) & |
|
|
(np_image[:, :, 1] >= min_green) & (np_image[:, :, 1] <= max_green) & |
|
|
(np_image[:, :, 2] >= min_blue) & (np_image[:, :, 2] <= max_blue) |
|
|
).astype(np.uint8) |
|
|
|
|
|
|
|
|
inverted_mask = 1 - mask |
|
|
labeled_mask, num_features = label(inverted_mask) |
|
|
|
|
|
|
|
|
for i, region in enumerate(find_objects(labeled_mask)): |
|
|
if region is not None: |
|
|
|
|
|
area = np.sum(labeled_mask[region] == i + 1) |
|
|
|
|
|
if area < 3000: |
|
|
inverted_mask[region] = np.where(labeled_mask[region] == i + 1, 0, inverted_mask[region]) |
|
|
|
|
|
|
|
|
filtered_mask = 1 - inverted_mask |
|
|
|
|
|
|
|
|
mask_image = Image.fromarray((filtered_mask * 255).astype(np.uint8)) |
|
|
|
|
|
return mask_image |
|
|
|
|
|
|
|
|
examples = [["cacao_1.png"], ["cacao_2.jpg"]] |
|
|
|
|
|
|
|
|
css = """ |
|
|
.app-container { background-color: white; } |
|
|
.title-container { |
|
|
background-color: white; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
height: 300px; |
|
|
font-size: 24px; |
|
|
font-weight: bold; |
|
|
text-align: center; |
|
|
} |
|
|
.centered-image { |
|
|
display: block; |
|
|
margin: auto; |
|
|
} |
|
|
""" |
|
|
|
|
|
|
|
|
with gr.Blocks(css=css) as demo: |
|
|
|
|
|
with gr.Row(): |
|
|
gr.Image(value="Cacaotin.png", width=300, height=300, elem_id="centered-image") |
|
|
gr.Markdown("<div class='title-container'>Fermentation Level Classification for Cocoa Beans</div>") |
|
|
|
|
|
|
|
|
gr.Markdown("<center><a href='https://github.com/kebincontreras/cocoa_beans_interfaces' target='_blank'><button style='background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 5px; font-size: 16px;'>View on GitHub</button></a></center>") |
|
|
|
|
|
|
|
|
with gr.Row(): |
|
|
img_input = gr.Image(label="Upload Image") |
|
|
img_output = gr.Image(label="Image with Generated Mask") |
|
|
|
|
|
|
|
|
btn_classify = gr.Button("Generate Mask for Fermentation Level") |
|
|
btn_classify.click(generate_mask, inputs=img_input, outputs=img_output) |
|
|
|
|
|
|
|
|
gr.Examples( |
|
|
examples=examples, |
|
|
inputs=img_input, |
|
|
label="Example Images" |
|
|
) |
|
|
|
|
|
|
|
|
gr.Markdown(""" |
|
|
**Cacao Classes According to NTC1252:2021:** |
|
|
- **a) Well-fermented:** Optimal fermentation process. |
|
|
- **b) Partially fermented:** Incomplete fermentation process. |
|
|
- **c) Non-fermented:** Lack of adequate fermentation. |
|
|
""") |
|
|
gr.Image(value="cacao.png", label="a) Well-fermented, b) Partially fermented, c) Non-fermented") |
|
|
|
|
|
|
|
|
gr.Markdown("**Explanation According to NTC1252:2021:** Here you can explain how the NTC1252:2021 norm applies to the classification of fermentation levels.") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |
|
|
|