Spaces:
Sleeping
Sleeping
| # import detectron2 | |
| # import torch | |
| # | |
| # # Check this in logs | |
| # try: | |
| # print(f"Is CUDA available: {torch.cuda.is_available()}") | |
| # # True | |
| # print(f"CUDA device: {torch.cuda.get_device_name(torch.cuda.current_device())}") | |
| # except: | |
| # print('Couldnt find CUDA device') | |
| import base64 | |
| import tempfile | |
| import cv2 | |
| from io import BytesIO | |
| import pandas as pd | |
| from PIL import Image | |
| from shiny import App, ui, render, reactive, Session | |
| from python_utils import load_model | |
| # Load data and compute static values | |
| from shared import app_dir | |
| # Load the prediction model | |
| predictor = load_model() | |
| app_ui = ui.page_fluid( | |
| ui.include_css("styles.css"), | |
| ui.panel_title(ui.div("Orchid TZ Viability Analyzer", class_="navbar-title")), | |
| ui.div( | |
| ui.download_button("download", "Download Results", class_="btn-primary"), | |
| style="position: absolute; top: 10px; right: 10px;" | |
| ), | |
| ui.layout_sidebar( | |
| ui.sidebar( | |
| ui.input_file("upload", "Upload Images", | |
| multiple=True, | |
| accept=[".png", ".jpg", ".jpeg"]), | |
| ui.input_action_button("analyze", "Analyze", class_="btn-success"), | |
| width =300 | |
| ), | |
| ui.output_ui("results_container"), | |
| border=False, | |
| border_radius=False | |
| ) | |
| ) | |
| def server(input, output, session: Session): | |
| analysis_results = reactive.Value([]) | |
| async def process_images(): | |
| files = input.upload() | |
| if not files: | |
| return | |
| results = [] | |
| with tempfile.TemporaryDirectory() as temp_dir: | |
| for idx, file in enumerate(files): | |
| # Read image using OpenCV | |
| im = cv2.imread(file["datapath"]) | |
| # Convert BGR to RGB for display | |
| im_rgb = cv2.cvtColor(im, cv2.COLOR_BGR2RGB) | |
| pil_img = Image.fromarray(im_rgb) | |
| # Convert to base64 for HTML display | |
| buffered = BytesIO() | |
| pil_img.save(buffered, format="PNG") | |
| img_base64 = base64.b64encode(buffered.getvalue()).decode() | |
| # Run prediction with original BGR image | |
| prediction = predictor(im) | |
| classes = prediction["instances"].pred_classes.tolist() | |
| results.append({ | |
| "filename": file["name"], | |
| "image": img_base64, | |
| **prediction, | |
| "viable": classes.count(0), | |
| "non-viable": classes.count(1), | |
| "empty": classes.count(2), | |
| "total": len(classes) | |
| }) | |
| # Update reactive value | |
| analysis_results.set(results) | |
| def results_container(): | |
| results = analysis_results.get() | |
| if not results: | |
| return ui.div("No results yet. Upload images and click 'Analyze'.", | |
| class_="text-muted") | |
| return ui.div( | |
| [ui.div( | |
| ui.row( | |
| ui.column(4, ui.img(src=f"data:image/png;base64,{r['image']}")), | |
| # ui.column(4, ui.output_plot("output", result=r)), | |
| ), | |
| ui.h5(r['filename'], style="margin-top: 15px;"), | |
| ui.div( | |
| ui.span(f"Viable = {r.get('viable', '? ')}", style="margin: 0 15px;"), | |
| ui.span(f"Nonviable = {r.get('nonviable', '? ')}", style="margin: 0 15px;"), | |
| ui.span(f"Empty = {r.get('empty', '? ')}", style="margin: 0 15px;"), | |
| ui.span(f"Total = {r.get('total', '? ')}", style="margin: 0 15px;"), | |
| class_="results-text" | |
| ), | |
| class_="card p-3" | |
| ) for r in results] | |
| ) | |
| # @render.plot | |
| # def output(result): | |
| # fig = plt.imshow(cv2.imread(r['image'])) | |
| # print(result) | |
| # return fig | |
| def download(): | |
| results = analysis_results.get() | |
| df = pd.DataFrame([{ | |
| "Filename": r["filename"], | |
| "Viable": r.get("viable", ""), | |
| "Nonviable": r.get("nonviable", ""), | |
| "Empty": r.get("empty", ""), | |
| "Total": r.get("total", "") | |
| } for r in results]) | |
| # Create in-memory CSV file | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as tmp: | |
| df.to_csv(tmp.name, index=False) | |
| return tmp.name | |
| app = App(app_ui, server) | |
| # -------------------------------------------------------- | |
| # Reactive calculations and effects | |
| # -------------------------------------------------------- | |