himanithattil/casting-defect-detector
0
1import gradio as gr2import google.generativeai as genai3import json4import base645from PIL import Image6import io7 8API_KEYS = [9 "AIzaSyCGXMZfEXCSnrnpgjKR4SWfxmDOKlDb8Hw",10 "AIzaSyDU9obviYZuOCv9ZfZ5MCKknNzehzg-t0s",11 "AIzaSyC2jMIqXg0_YsWW4auDICBfq492YQZR9gk",12 "AIzaSyAtZxL_93uJtkDYRxJdm5uIJmP_Jn85eJA",13 "AIzaSyCsrX1yc60oYXQDmzs5W3EgRIrCQD8JE0s",14 "AIzaSyCOYn9vyn9YzNMNNA7mCiyBI-Xp-hFOHmE",15 "AIzaSyAUCnobLkJ00HVr1zNWnXLfEGFOuJNNlvc",16 "AIzaSyCuxS3UOu5ELWQ5GM98lpuomnLL8bgk_ps"17]18 19PROMPT = """You are an experienced casting quality inspector with 20 years of experience. Analyze this casting component image.20 21UNDERSTAND THIS FIRST:22- Investment cast components naturally have a rough grainy surface — this is NORMAL and NOT a defect23- Sand cast components have an even rougher surface — this is NORMAL and NOT a defect24- Machined components have smooth uniform surfaces — this is NORMAL25- Logos, text, symbols and design features on components are NORMAL26- Parting lines from molds are NORMAL27 28PASS the component if:29- It has normal casting surface texture even if rough or grainy30- It has logos symbols or text markings on it31- It has defined curves and design features32- It looks structurally complete with no damage33 34FAIL the component ONLY if you can clearly see:35- CRACKS — irregular jagged fracture lines clearly going through the material36- GAS POROSITY — multiple clearly visible holes or pits that go INTO the material37- COLD SHUT — a clear seam line where two metal flows did not bond38- SHRINKAGE CAVITY — a clearly sunken collapsed area39- BROKEN SECTION — a missing or broken chunk of the component40- MISRUN — incomplete filling with missing sections41 42KEY RULE:43- Rough grainy surface = NORMAL = PASS44- Logos and markings = NORMAL = PASS 45- Only structural damage = FAIL46- When in doubt always PASS47 48Respond with ONLY this JSON, no extra text:49{"verdict":"PASS or FAIL","defects":[{"type":"exact defect name like Gas Porosity / Shrinkage Cavity / Cold Shut / Hot Tear / Surface Crack","cause":"technical cause","remedy":"technical remedy"}],"summary":"one technical sentence"}50If PASS use empty defects array. Max 2 defects. Return ONLY JSON."""51 52def analyze_casting(image):53 if image is None:54 return json.dumps({"verdict": "ERROR", "defects": [], "summary": "No image provided"})55 56 # Convert PIL image to bytes57 img_byte_arr = io.BytesIO()58 image.save(img_byte_arr, format='JPEG')59 img_byte_arr = img_byte_arr.getvalue()60 img_base64 = base64.b64encode(img_byte_arr).decode('utf-8')61 62 # Try each API key63 for key in API_KEYS:64 try:65 genai.configure(api_key=key)66 model = genai.GenerativeModel('gemini-2.5-flash')67 68 response = model.generate_content([69 PROMPT,70 {"mime_type": "image/jpeg", "data": img_base64}71 ])72 73 raw = response.text.strip()74 clean = raw.replace('```json', '').replace('```', '').strip()75 76 # Extract JSON77 import re78 json_match = re.search(r'\{[\s\S]*\}', clean)79 if json_match:80 result = json.loads(json_match.group())81 return json.dumps(result)82 except Exception as e:83 continue84 85 return json.dumps({86 "verdict": "ERROR",87 "defects": [],88 "summary": "All API keys quota exceeded. Please try again later."89 })90 91iface = gr.Interface(92 fn=analyze_casting,93 inputs=gr.Image(type="pil", label="Upload Casting Image"),94 outputs=gr.Textbox(label="Result"),95 title="Casting Defect Detector",96 description="Upload a casting image to detect defects"97)98 99iface.launch()