import gradio as gr from PIL import Image from pix2tex.cli import LatexOCR import sympy as sp from sympy.parsing.latex import parse_latex import re model = LatexOCR() def preprocess_handwritten_image(pil_img): return pil_img.convert('RGB') # --- Tab 1 cleaner (UNCHANGED) --- def clean_latex(latex): latex = latex.replace('\\ ', '') latex = latex.replace('\\\\', '\\') latex = re.sub(r'\\[ \t\n\r\f\v]*', '', latex) latex = re.sub(r'\\([+\-=])', r'\1', latex) replacements = { r'\\chi': 'x', r'chi': 'x', r'\\xi': 'x', r'xi': 'x', r'\\alpha': 'x', r'alpha': 'x', r'\\beta': 'b', r'beta': 'b', r'\\gamma': 'y', r'gamma': 'y', r'\\vartheta': '3', r'vartheta': '3', r'\\mathcalW': 'x', r'mathcalW': 'x', r'\\pi': 'pi', r'pi': 'pi', r'\\mathrm': '', r'mathrm': '', } for wrong, correct in replacements.items(): latex = re.sub(wrong, correct, latex) latex = re.sub(r'\\(cal|mathcal)\s*\{?\s*[Xx]\s*\}?', 'x', latex) latex = re.sub(r'\\(cal|mathcal)\s*\{?\s*[Yy]\s*\}?', 'y', latex) latex = re.sub(r'\\(cal|mathcal)\s*\{?\s*[Zz]\s*\}?', 'z', latex) latex = latex.replace('cal x', 'x').replace('cal X', 'x') latex = latex.replace('mathcal x', 'x').replace('mathcal X', 'x') latex = latex.replace('{', '').replace('}', '') latex = latex.strip().rstrip(',.') latex = re.sub(r'(?])=(?![=<>])', ' = ', latex) replacements = { 'chi': 'x', 'xi': 'x', 'alpha': 'x', 'beta': 'b', 'gamma': 'y', 'vartheta': '3', 'mathcal': '', 'cal': '', 'mathrm': '' } for wrong, right in replacements.items(): latex = re.sub(wrong, right, latex) return latex.strip() # --- Polynomial Solver (unchanged) --- def solve_polynomial(image): try: img = preprocess_handwritten_image(image) latex_result = model(img) if not latex_result or len(latex_result.strip()) < 2: return "โŒ Could not extract valid LaTeX from image.", "", "" cleaned_latex = clean_latex(latex_result) expr = parse_latex(cleaned_latex) expr = expr.subs(sp.pi, sp.Float(3.1416)).subs(sp.E, sp.Float(2.7183)) if not isinstance(expr, sp.Equality): raise ValueError("Expression is not an equation.") lhs = expr.lhs - expr.rhs if not lhs.is_polynomial(): raise ValueError("Not a polynomial") output = f"## ๐Ÿ“„ Extracted LaTeX\n```latex\n{latex_result}\n```\n" output += f"---\n## ๐Ÿงน Cleaned LaTeX\n```latex\n{cleaned_latex}\n```\n" output += f"---\n## ๐Ÿง  Parsed Expression\n$$ {sp.latex(expr)} $$\n" factor = sp.factor(lhs) output += f"---\n## โœ๏ธ Standard Form\n$$ {sp.latex(lhs)} = 0 $$\n" output += f"---\n## ๐Ÿงฉ Factorized\n$$ {sp.latex(factor)} = 0 $$\n" x = next(iter(lhs.free_symbols)) roots = sp.solve(lhs, x) output += "## โœ… Roots\n" output += "$$\n\\begin{aligned}\n" for i, r in enumerate(roots, 1): root_val = sp.N(r, 6) output += f"\\text{{Root {i}}}:\\quad x &\\approx {sp.latex(root_val)} \\\\\n" output += "\\end{aligned}\n$$\n" return output, cleaned_latex, "" except Exception as e: return f"โŒ Error: {str(e)}", "", "" # --- NEW Multi-image System Solver --- def solve_system_multi(img1, img2, img3): images = [img1, img2, img3] cleaned_equations = [] raw_outputs = [] for img in images: if img is None: continue try: img = preprocess_handwritten_image(img) latex = model(img) raw_outputs.append(latex) cleaned = clean_latex2(latex) parsed = parse_latex(cleaned) if isinstance(parsed, sp.Equality): cleaned_equations.append(parsed) except: continue if len(cleaned_equations) < 2: return f"โŒ Could not parse enough valid equations." symbols = set() for eq in cleaned_equations: symbols.update(eq.free_symbols) sol = sp.solve(cleaned_equations, list(symbols), dict=True) output = "## ๐Ÿ“„ Raw LaTeX:\n" for latex in raw_outputs: output += f"- ```latex\n{latex}\n```\n" output += "---\n## โœ๏ธ Parsed Equations:\n" for eq in cleaned_equations: output += f"$$ {sp.latex(eq)} $$\n" output += "---\n## โœ… Solution:\n" if sol: output += "$$" + sp.latex(sol[0]) + "$$" else: output += "โŒ No solution found or system may be inconsistent." return output # === UI === with gr.Blocks() as demo: with gr.Tab("๐Ÿ–ผ๏ธ Parse from Image"): image_input = gr.Image(type="pil", label="๐Ÿ“ท Upload Image of Polynomial") hidden_latex = gr.Textbox(visible=False) explanation_prompt = gr.Textbox(visible=False) output_box = gr.Markdown(label="๐Ÿ“‹ Step-by-step Solution") submit_btn = gr.Button("๐Ÿ” Solve") submit_btn.click(fn=solve_polynomial, inputs=[image_input], outputs=[output_box, hidden_latex, explanation_prompt]) with gr.Tab("๐Ÿ“ Solve System (Multi-Image)"): img1 = gr.Image(type="pil", label="๐Ÿ“ท Equation 1") img2 = gr.Image(type="pil", label="๐Ÿ“ท Equation 2") img3 = gr.Image(type="pil", label="๐Ÿ“ท Equation 3 (Optional)") sys_output = gr.Markdown(label="๐Ÿ“‹ Solved System Output") sys_btn = gr.Button("๐Ÿ“Œ Solve System") sys_btn.click(fn=solve_system_multi, inputs=[img1, img2, img3], outputs=[sys_output]) if __name__ == "__main__": demo.launch()