nehakothari commited on
Commit
435fe24
·
verified ·
1 Parent(s): c247dc3

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +151 -0
app.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ import pymssql
3
+ import pandas as pd
4
+ import torch
5
+ import cv2
6
+ import pytesseract
7
+ from transformers import Qwen2VLForConditionalGeneration, AutoProcessor
8
+ from qwen_vl_utils import process_vision_info
9
+
10
+ # Initialize Flask app
11
+ app = Flask(__name__)
12
+
13
+ # Initialize model and processor
14
+ model = Qwen2VLForConditionalGeneration.from_pretrained("Qwen/Qwen2-VL-2B-Instruct-AWQ", torch_dtype="auto")
15
+ if torch.cuda.is_available():
16
+ model.to("cuda")
17
+ processor = AutoProcessor.from_pretrained("Qwen/Qwen2-VL-2B-Instruct-AWQ")
18
+
19
+ pytesseract.pytesseract_cmd = r'/usr/bin/tesseract'
20
+
21
+ # Function to preprocess the image for OCR
22
+ def preprocess_image(image_path):
23
+ image = cv2.imread(image_path)
24
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
25
+ _, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
26
+ return binary
27
+
28
+ # Function to extract text using OCR
29
+ def ocr_extract_text(image_path):
30
+ preprocessed_image = preprocess_image(image_path)
31
+ return pytesseract.image_to_string(preprocessed_image)
32
+
33
+ # Function to process image and extract details
34
+ def process_image(image_path):
35
+ try:
36
+ messages = [{
37
+ "role": "user",
38
+ "content": [
39
+ {"type": "image", "image": image_path},
40
+ {"type": "text", "text": (
41
+ "Extract the following details from the invoice:\n"
42
+ "- 'invoice_number'\n"
43
+ "- 'date'\n"
44
+ "- 'place'\n"
45
+ "- 'amount' (monetary value in the relevant currency)\n"
46
+ "- 'category' (based on the invoice type)"
47
+ )}
48
+ ]
49
+ }]
50
+
51
+ text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
52
+ image_inputs, video_inputs = process_vision_info(messages)
53
+ inputs = processor(text=[text], images=image_inputs, videos=video_inputs, padding=True, return_tensors="pt")
54
+ inputs = inputs.to(model.device)
55
+
56
+ generated_ids = model.generate(**inputs, max_new_tokens=128)
57
+ output_text = processor.batch_decode(generated_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)
58
+
59
+ return parse_details(output_text[0])
60
+
61
+ except Exception as e:
62
+ print(f"Model failed, falling back to OCR: {e}")
63
+ ocr_text = ocr_extract_text(image_path)
64
+ return parse_details(ocr_text)
65
+
66
+ # Function to parse details from text
67
+ def parse_details(details):
68
+ parsed_data = {
69
+ "Invoice Number": None,
70
+ "Date": None,
71
+ "Place": None,
72
+ "Amount": None,
73
+ "Category": None
74
+ }
75
+
76
+ lines = details.split("\n")
77
+ for line in lines:
78
+ lower_line = line.lower()
79
+ if "invoice" in lower_line:
80
+ parsed_data["Invoice Number"] = line.split(":")[-1].strip()
81
+ elif "date" in lower_line:
82
+ parsed_data["Date"] = line.split(":")[-1].strip()
83
+ elif "place" in lower_line:
84
+ parsed_data["Place"] = line.split(":")[-1].strip()
85
+ elif any(keyword in lower_line for keyword in ["total", "amount", "cost"]):
86
+ parsed_data["Amount"] = line.split(":")[-1].strip()
87
+ else:
88
+ parsed_data["Category"] = "General"
89
+
90
+ return parsed_data
91
+
92
+ # Function to store DataFrame to Azure SQL Database
93
+ def store_to_azure_sql(dataframe):
94
+ conn_str = (
95
+ "Driver={ODBC Driver 17 for SQL Server};"
96
+ "Server=35.227.148.156;" # Hardcoded IP address
97
+ "Database=dbo.Invoices;"
98
+ "UID=pio-admin;"
99
+ "PWD=Poctest123#;"
100
+ )
101
+ try:
102
+ with pymssql.connect(conn_str) as conn:
103
+ cursor = conn.cursor()
104
+ create_table_query = """
105
+ IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='Invoices' AND xtype='U')
106
+ CREATE TABLE Invoices (
107
+ InvoiceNumber NVARCHAR(255),
108
+ Date NVARCHAR(255),
109
+ Place NVARCHAR(255),
110
+ Amount NVARCHAR(255),
111
+ Category NVARCHAR(255)
112
+ )
113
+ """
114
+ cursor.execute(create_table_query)
115
+
116
+ for _, row in dataframe.iterrows():
117
+ insert_query = """
118
+ INSERT INTO Invoices (InvoiceNumber, Date, Place, Amount, Category)
119
+ VALUES (%s, %s, %s, %s, %s)
120
+ """
121
+ cursor.execute(insert_query, row['Invoice Number'], row['Date'], row['Place'], row['Amount'], row['Category'])
122
+ conn.commit()
123
+ print("Data successfully stored in Azure SQL Database.")
124
+ except Exception as e:
125
+ print(f"Error storing data to database: {e}")
126
+
127
+ @app.route('/process_invoice', methods=['POST'])
128
+ def process_invoice():
129
+ try:
130
+ # Get the image file from the request
131
+ image_file = request.files['file']
132
+ image_path = "temp_image.jpg"
133
+ image_file.save(image_path)
134
+
135
+ # Process the image
136
+ details = process_image(image_path)
137
+
138
+ # Convert details to a DataFrame
139
+ df = pd.DataFrame([details])
140
+
141
+ # Store in Azure SQL
142
+ store_to_azure_sql(df)
143
+
144
+ # Return the extracted details and status
145
+ return jsonify({"extracted_details": details, "status": "Data stored successfully"})
146
+
147
+ except Exception as e:
148
+ return jsonify({"error": str(e)}), 500
149
+
150
+ if __name__ == "__main__":
151
+ app.run(host="0.0.0.0", port=5000)