pawanmau01 commited on
Commit
fb12fe1
1 Parent(s): 6391925

Added App Folder

Browse files
app/__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask
2
+ from ultralytics import YOLO
3
+
4
+ def create_app():
5
+ app = Flask(__name__)
6
+ from .api import ocr_bp
7
+ app.register_blueprint(ocr_bp)
8
+
9
+ with app.app_context():
10
+ # Load model once
11
+ app.models = {
12
+ 'adhaarModel': YOLO('models/aadhaarYolov8.pt'),
13
+ 'panModel': YOLO('models/PanYolov8.pt') # Load additional models as needed
14
+ }
15
+
16
+ return app
app/api.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint
2
+ import requests
3
+ import os
4
+ from .routes.adhaarApi import ocrAdhaar
5
+ from .routes.panApi import ocrPan
6
+ ocr_bp = Blueprint('ocr', __name__)
7
+ session = requests.Session()
8
+ mode = os.getenv("PROJECT_MODE")
9
+
10
+ @ocr_bp.route('/ocrPan', methods=['POST'])
11
+ def getResponse_Pan():
12
+ return ocrPan(mode, session)
13
+
14
+ @ocr_bp.route('/ocrAdhaar', methods=['POST'])
15
+ def getResponse_Adhaar():
16
+ return ocrAdhaar(mode, session)
app/routes/adhaarApi.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from flask import request, jsonify, current_app
3
+ from PIL import Image, UnidentifiedImageError
4
+ from io import BytesIO
5
+ import base64
6
+ import requests
7
+ from ..services.adhaarServices.ocr import process_results
8
+ import io
9
+ def ocrAdhaar(mode, session):
10
+ try:
11
+ print("API HIT ************* AADHAAROCR")
12
+ data = request.get_json()
13
+ if not data:
14
+ return jsonify({"error": "Invalid request payload"}), 400
15
+
16
+ if mode == "prod":
17
+ if not data.get('image'):
18
+ return jsonify({"error": "Image data/buffer is required"}), 400
19
+
20
+ #removing 'data:image/png,base64 ' from buffer.
21
+ imgBuffer = data.get('image')
22
+ imgBuffer = re.sub("^data:image/.+;base64,", "", imgBuffer)
23
+ # Adjust base64 string padding
24
+ if len(imgBuffer) % 4:
25
+ imgBuffer += '=' * (4 - len(imgBuffer) % 4)
26
+
27
+ try:
28
+ img_data = base64.b64decode(imgBuffer)
29
+ img = Image.open(BytesIO(img_data))
30
+ img.verify() # Verify image format
31
+ img = Image.open(io.BytesIO(img_data)) # Re-open image after verification
32
+ except (base64.binascii.Error, ValueError) as decode_err:
33
+ return jsonify({"error": f"Image decoding failed: {str(decode_err)}"}), 400
34
+ except UnidentifiedImageError:
35
+ return jsonify({"error": "Unable to identify image format."}), 400
36
+
37
+ elif mode == "dev":
38
+ if not data.get('imgUrl'):
39
+ return jsonify({"error": "Image URL is required"}), 400
40
+
41
+ img_url = data.get('imgUrl')
42
+ response = session.get(img_url)
43
+ response.raise_for_status()
44
+ img = Image.open(BytesIO(response.content))
45
+ img.verify() # Verify image format
46
+ img = Image.open(BytesIO(response.content)) # Re-open image after verification
47
+
48
+ else:
49
+ return jsonify({"error": "Invalid mode configuration"}), 500
50
+
51
+ # Check image format
52
+ if img.format not in ['JPEG', 'JPG', 'PNG']:
53
+ return jsonify({"error": "Invalid image format. Only JPG and PNG are supported."}), 400
54
+
55
+ # Run detection
56
+ model = current_app.models.get('adhaarModel')
57
+ results = model.predict(source=img, save=False)
58
+ extracted_data = process_results(results, img)
59
+
60
+ if extracted_data.get('statusCode') == 400:
61
+ return jsonify(extracted_data), 400
62
+
63
+ return jsonify(extracted_data), 200
64
+ except requests.RequestException as req_err:
65
+ return jsonify({"error": f"Image download failed: {str(req_err)}"}), 500
66
+ except UnidentifiedImageError:
67
+ return jsonify({"error": "Unable to identify image format."}), 400
68
+ except Exception as e:
69
+ current_app.logger.error(f"Unexpected error: {str(e)}")
70
+ return jsonify({"error": "An unexpected error occurred."}), 500
app/routes/panApi.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from flask import request, jsonify, current_app
3
+ from PIL import Image, UnidentifiedImageError
4
+ from io import BytesIO
5
+ import base64
6
+ import requests
7
+ from ..services.panServices.panOcr import process_results
8
+ import io
9
+ def ocrPan(mode, session):
10
+ try:
11
+ print("API HIT ************* PANOCR")
12
+ data = request.get_json()
13
+ if not data:
14
+ return jsonify({"error": "Invalid request payload"}), 400
15
+
16
+ if mode == "prod":
17
+ if not data.get('image'):
18
+ return jsonify({"error": "Image data/buffer is required"}), 400
19
+
20
+ #removing 'data:image/png,base64 ' from buffer.
21
+ imgBuffer = data.get('image')
22
+ imgBuffer = re.sub("^data:image/.+;base64,", "", imgBuffer)
23
+ # Adjust base64 string padding
24
+ if len(imgBuffer) % 4:
25
+ imgBuffer += '=' * (4 - len(imgBuffer) % 4)
26
+
27
+ try:
28
+ img_data = base64.b64decode(imgBuffer)
29
+ img = Image.open(BytesIO(img_data))
30
+ img.verify() # Verify image format
31
+ img = Image.open(io.BytesIO(img_data)) # Re-open image after verification
32
+ except (base64.binascii.Error, ValueError) as decode_err:
33
+ return jsonify({"error": f"Image decoding failed: {str(decode_err)}"}), 400
34
+ except UnidentifiedImageError:
35
+ return jsonify({"error": "Unable to identify image format."}), 400
36
+
37
+ elif mode == "dev":
38
+ if not data.get('imgUrl'):
39
+ return jsonify({"error": "Image URL is required"}), 400
40
+
41
+ img_url = data.get('imgUrl')
42
+ response = session.get(img_url)
43
+ response.raise_for_status()
44
+ img = Image.open(BytesIO(response.content))
45
+ img.verify() # Verify image format
46
+ img = Image.open(BytesIO(response.content)) # Re-open image after verification
47
+
48
+ else:
49
+ return jsonify({"error": "Invalid mode configuration"}), 500
50
+
51
+ # Check image format
52
+ if img.format not in ['JPEG', 'JPG', 'PNG']:
53
+ return jsonify({"error": "Invalid image format. Only JPG and PNG are supported."}), 400
54
+
55
+ # Run detection
56
+ model = current_app.models.get('panModel')
57
+ results = model.predict(source=img, save=False)
58
+ extracted_data = process_results(results, img)
59
+
60
+ if extracted_data.get('statusCode') == 400:
61
+ return jsonify(extracted_data), 400
62
+
63
+ return jsonify(extracted_data), 200
64
+ except requests.RequestException as req_err:
65
+ return jsonify({"error": f"Image download failed: {str(req_err)}"}), 500
66
+ except UnidentifiedImageError:
67
+ return jsonify({"error": "Unable to identify image format."}), 400
68
+ except Exception as e:
69
+ current_app.logger.error(f"Unexpected error: {str(e)}")
70
+ return jsonify({"error": "An unexpected error occurred."}), 500
app/services/adhaarServices/adhaarDataExtractor.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import datetime
2
+
3
+ def extract_details(texts):
4
+ details = {'name': '', 'gender': '', 'dob': '', 'aadhaarNo': ''}
5
+
6
+ current_year = datetime.datetime.now().year
7
+
8
+ for text in texts:
9
+ # Check if colon exists in text and split accordingly
10
+ if ':' in text:
11
+ text = text.split(':')[1].strip()
12
+
13
+ cleaned_text = text.replace(':', '').strip()
14
+
15
+ # Remove leading non-alphabetic characters for gender detection and strip spaces
16
+ cleaned_gender = cleaned_text.lstrip('.-/').strip()
17
+
18
+ # Check if the text is the name (only alphabets, spaces, and possibly dots)
19
+ if (all(char.isalpha() or char.isspace() or char == '.' for char in cleaned_text)
20
+ and cleaned_gender.lower() not in ['male', 'female']):
21
+ details['name'] = cleaned_text
22
+
23
+ # Check if the text is the DOB (format: dd/mm/yyyy or yyyy)
24
+ elif (len(cleaned_text) == 4 and
25
+ cleaned_text.isdigit() and
26
+ 1900 < int(cleaned_text) < current_year):
27
+ details['dob'] = cleaned_text
28
+
29
+ # Check if the text is the DOB (format: dd/mm/yyyy or dd-mm-yyyy)
30
+ elif (len(cleaned_text) == 10 and
31
+ (cleaned_text[2] in ['/', '-']) and
32
+ (cleaned_text[5] in ['/', '-']) and
33
+ cleaned_text.replace('/', '').replace('-', '').isdigit()):
34
+ details['dob'] = cleaned_text
35
+
36
+ # Check if the text is the gender (either 'Male' or 'Female')
37
+ elif cleaned_gender.lower() in ['male', 'female']:
38
+ details['gender'] = cleaned_gender.capitalize()
39
+
40
+ # Check if the text is the Aadhaar number (12 digits after removing spaces)
41
+ elif cleaned_text.replace(' ', '').isdigit() and len(cleaned_text.replace(' ', '')) == 12:
42
+ details['aadhaarNo'] = cleaned_text
43
+
44
+ # Check if any key's value is empty
45
+ if any(value == '' for value in details.values()):
46
+ error_key = next(key for key, value in details.items() if value == '')
47
+ result = {
48
+ 'statusCode': 400,
49
+ 'result': details,
50
+ 'error': f'{error_key} value is not found due to bad image.'
51
+ }
52
+ else:
53
+ result = {
54
+ 'statusCode': 200,
55
+ 'result': details,
56
+ 'error': ''
57
+ }
58
+
59
+ return result
app/services/adhaarServices/ocr.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from io import BytesIO
2
+ from ...utils.azureOCR import analyze_image
3
+ from ...utils.imageUtils import resize_if_needed, all_cropped_images_to_one_image
4
+ from app.services.adhaarServices.adhaarDataExtractor import extract_details
5
+
6
+ def process_results(results, img):
7
+ precision_data = {label: {"correct": 0, "total": 0} for label in ["aadharNo", "name", "dob", "gender", "address"]}
8
+ confidence_threshold = 0.3
9
+ input_image_format = img.format if img.format else "PNG"
10
+ valid_formats = ["JPEG", "PNG", "BMP", "GIF", "TIFF"]
11
+ input_image_format = input_image_format if input_image_format in valid_formats else "PNG"
12
+
13
+ label_to_image = {}
14
+ extracted_data = {"adhaarNo": "", "dob": "", "gender": "", "name": "", "address": ""}
15
+ for result in results:
16
+ for bbox, cls, conf in zip(result.boxes.xyxy, result.boxes.cls, result.boxes.conf):
17
+ label = ["aadharNo", "dob", "gender", "name", "address"][int(cls)]
18
+ print(label, conf)
19
+ if conf < confidence_threshold or label == "address":
20
+ continue
21
+
22
+ x1, y1, x2, y2 = map(int, bbox.tolist())
23
+ crop_img = img.crop((x1, y1, x2, y2))
24
+ crop_img = resize_if_needed(crop_img)
25
+
26
+ if label not in label_to_image or label_to_image[label][1] < conf:
27
+ label_to_image[label] = (crop_img, conf)
28
+ precision_data[label]["total"] += 1
29
+ precision_data[label]["correct"] += 1 # Replace with actual OCR validation check
30
+
31
+ cropped_images = [img for label, (img, conf) in sorted(label_to_image.items()) if label != "address"]
32
+ final_image = all_cropped_images_to_one_image(cropped_images, separator_image_path='app/utils/seprator3.png')
33
+
34
+ buffer = BytesIO()
35
+ final_image.save(buffer, format=input_image_format)
36
+ buffer.seek(0)
37
+
38
+ response = analyze_image(buffer.getvalue(), input_image_format)
39
+ # print(response)
40
+ lines = response['readResult']['blocks'][0]['lines']
41
+ texts = [line['text'] for line in lines]
42
+ print(texts)
43
+ extracted_data = extract_details(texts)
44
+ return extracted_data
app/services/panServices/panDataExtractor.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+ def extract_panData(data):
4
+ unwanted_words = ["Name","/Name", "Date of Birth", "/Date of Birth", "Permanent Account Number", "Father's Name", "14 /Name", "/Father's Name"]
5
+
6
+ # Clean the array by removing unwanted words and invalid entries
7
+ cleaned_data = []
8
+ combination_pattern = re.compile(r'(?=.*[A-Za-z])(?=.*[0-9])(?=.*[!@#$%^&*(),?":{}|<>])')
9
+
10
+ for item in data:
11
+ if item not in unwanted_words and not combination_pattern.search(item):
12
+ cleaned_data.append(item)
13
+
14
+ # Initialize result object
15
+ result = {
16
+ "statusCode": 200,
17
+ "error": '',
18
+ "data": {
19
+ "panNo": '',
20
+ "name": '',
21
+ "fatherName": '',
22
+ "dob": ''
23
+ }
24
+ }
25
+
26
+ # Check and extract PAN number
27
+ print(cleaned_data)
28
+ pan_pattern = re.compile(r'^[A-Z]{5}[0-9]{4}[A-Z]$')
29
+ if len(cleaned_data) > 0 and pan_pattern.match(cleaned_data[3]):
30
+ result["data"]["panNo"] = cleaned_data[3]
31
+ else:
32
+ result["data"]["panNo"] = ''
33
+
34
+ # Check and extract name
35
+ name_pattern = re.compile(r'^[A-Za-z .]+$')
36
+ if len(cleaned_data) > 1 and name_pattern.match(cleaned_data[2]):
37
+ result["data"]["name"] = cleaned_data[2]
38
+ else:
39
+ result["data"]["name"] = ''
40
+
41
+ # Check and extract father's name
42
+ if len(cleaned_data) > 2 and name_pattern.match(cleaned_data[1]):
43
+ result["data"]["fatherName"] = cleaned_data[1]
44
+ else:
45
+ result["data"]["fatherName"] = ''
46
+
47
+ # Check and extract date of birth
48
+ dob_pattern = re.compile(r'^\d{2}[-/]\d{2}[-/]\d{4}$')
49
+ if len(cleaned_data) > 3 and dob_pattern.match(cleaned_data[0]):
50
+ result["data"]["dob"] = cleaned_data[0]
51
+ else:
52
+ result["data"]["dob"] = ''
53
+
54
+ # Check if any value is empty and set error message
55
+ for key, value in result["data"].items():
56
+ if value == '':
57
+ result["statusCode"] = 400
58
+ result["error"] = f"{key} value is not found due to bad image."
59
+ break
60
+
61
+ return result
app/services/panServices/panOcr.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from io import BytesIO
2
+ from ...utils.azureOCR import analyze_image
3
+ from ...utils.imageUtils import resize_if_needed, all_cropped_images_to_one_image
4
+ from .panDataExtractor import extract_panData
5
+
6
+ def process_results(results, img):
7
+ label_indices = {"dob": 0, "father": 1, "name": 2, "pan_num": 3}
8
+ confidence_threshold = 0.3
9
+ input_image_format = img.format if img.format else "PNG"
10
+ valid_formats = ["JPEG", "PNG", "BMP", "GIF", "TIFF"]
11
+ input_image_format = input_image_format if input_image_format in valid_formats else "PNG"
12
+
13
+ cropped_images_with_labels = []
14
+ precision_data = {label: {"correct": 0, "total": 0} for label in label_indices.keys()}
15
+ # extracted_data = {"pan_num": "", "name": "", "father": "", "dob": ""}
16
+
17
+ for result in results:
18
+ for bbox, cls, conf in zip(result.boxes.xyxy, result.boxes.cls, result.boxes.conf):
19
+ label = ["dob", "father", "name", "pan_num"][int(cls)]
20
+ print(label, conf)
21
+ if conf < confidence_threshold:
22
+ continue
23
+
24
+ x1, y1, x2, y2 = map(int, bbox.tolist())
25
+ crop_img = img.crop((x1, y1, x2, y2))
26
+ crop_img = resize_if_needed(crop_img)
27
+ crop_img.save(f"temp_{label}.png")
28
+ cropped_images_with_labels.append((crop_img, label_indices[label], conf))
29
+ precision_data[label]["total"] += 1
30
+ precision_data[label]["correct"] += 1 # Replace with actual OCR validation check
31
+
32
+ # Sort the images by their label indices in ascending order
33
+ cropped_images_with_labels.sort(key=lambda x: x[1])
34
+ print(cropped_images_with_labels, "cropped images with labels")
35
+ # Extract only the images for concatenation
36
+ cropped_images = [img for img, _, _ in cropped_images_with_labels]
37
+ # print(cropped_images, "cropped images")
38
+ if not cropped_images:
39
+ raise ValueError("No images were cropped.")
40
+
41
+ final_image = all_cropped_images_to_one_image(cropped_images, separator_image_path='app/utils/seprator3.png')
42
+ buffer = BytesIO()
43
+ final_image.save(buffer, format=input_image_format)
44
+ buffer.seek(0)
45
+
46
+ response = analyze_image(buffer.getvalue(), input_image_format)
47
+ print(response, "response")
48
+ lines = response['readResult']['blocks'][0]['lines']
49
+ texts = [line['text'] for line in lines]
50
+ print(texts, "text after microsoft ocr")
51
+ extracted_data = extract_panData(texts)
52
+ return extracted_data
app/utils/1.png ADDED
app/utils/2.png ADDED
app/utils/3.png ADDED
app/utils/4.png ADDED
app/utils/azureOCR.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+
3
+ def analyze_image(image_buffer, imgType):
4
+ url = 'https://portal.vision.cognitive.azure.com/api/demo/analyze?features=read'
5
+ headers = {
6
+ 'Accept': '*/*',
7
+ 'Accept-Language': 'en-GB,en;q=0.9,en-US;q=0.8',
8
+ 'Connection': 'keep-alive',
9
+ 'Cookie': 'ARRAffinity=ecee788152e01b1e3805dc3134d03cab01ed97f61e69beeb53fcc885e5d0e707; ARRAffinitySameSite=ecee788152e01b1e3805dc3134d03cab01ed97f61e69beeb53fcc885e5d0e707; ai_user=Hps6Ce/6zz/k9q5icFxuiU|2024-07-03T12:30:25.655Z; MicrosoftApplicationsTelemetryDeviceId=89ed4fb7-9ae7-4e71-af1e-add358e41b9e; MSFPC=GUID=cbf8cbf9ba1b48c69374f48574f06958&HASH=cbf8&LV=202407&V=4&LU=1720009794093; ai_session=ZABOsZ0VsIaPiorOXIr2B+|1720009825676|1720010022866',
10
+ 'DNT': '1',
11
+ 'Origin': 'https://portal.vision.cognitive.azure.com',
12
+ 'Referer': 'https://portal.vision.cognitive.azure.com/demo/extract-text-from-images',
13
+ 'Sec-Fetch-Dest': 'empty',
14
+ 'Sec-Fetch-Mode': 'cors',
15
+ 'Sec-Fetch-Site': 'same-origin',
16
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36 Edg/125.0.0.0',
17
+ 'api-call-origin': 'Microsoft.Cognitive.CustomVision.Portal',
18
+ 'content-disposition': 'form-data; name=Foo',
19
+ 'enctype': 'multipart/form-data',
20
+ 'request-context': 'appId=cid-v1:e2fac58d-316d-4cf3-a225-11d998b143db',
21
+ 'request-id': '|37e377d2a90c4c1ba78805dc901a47ac.fb0593645bfd456f',
22
+ 'sec-ch-ua': '"Microsoft Edge";v="125", "Chromium";v="125", "Not.A/Brand";v="24"',
23
+ 'sec-ch-ua-mobile': '?1',
24
+ 'sec-ch-ua-platform': '"Android"',
25
+ 'traceparent': '00-37e377d2a90c4c1ba78805dc901a47ac-fb0593645bfd456f-01'
26
+ }
27
+
28
+ files = {'file': ( f"allimage.{imgType}", image_buffer, f"image/{imgType}")}
29
+ response = requests.post(url, headers=headers, files=files)
30
+ if response.status_code != 200:
31
+ raise Exception(f"Failed to analyze image: {response.status_code} - {response.text}")
32
+ else:
33
+ return response.json()
34
+
35
+ # Example usage
36
+
37
+
38
+ # Example usage
39
+ # file_path = '/path/to/your/image.png'
40
+ # url = 'https://portal.vision.cognitive.azure.com/api/demo/analyze?features=read'
41
+ # response = analyze_image(file_path, url)
42
+ # print(response)
app/utils/imageUtils.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image
2
+ import cv2
3
+ import numpy as np
4
+
5
+ def resize_if_needed(image):
6
+ width, height = image.size
7
+ if width < 50 or height < 50:
8
+ scale = max(70 / width, 70 / height)
9
+ elif width > 16000 or height > 16000:
10
+ scale = min(16000 / width, 16000 / height)
11
+ else:
12
+ return image
13
+ return image.resize((int(width * scale), int(height * scale)), Image.LANCZOS)
14
+
15
+ def center_on_white_background(image):
16
+ width, height = image.size
17
+ if width < 150 and height < 50:
18
+ background = Image.new('RGB', (150, 150), (255, 255, 255))
19
+ x, y = (150 - width) // 2, (150 - height) // 2
20
+ background.paste(image, (x, y))
21
+ return background
22
+ return image
23
+
24
+ def all_cropped_images_to_one_image(cropped_images, separator_image_path):
25
+ separator_image = Image.open(separator_image_path)
26
+ separator_height = separator_image.height
27
+
28
+ total_height = sum(img.height for img in cropped_images) + (len(cropped_images) - 1) * separator_height
29
+ print("Total Height:", total_height)
30
+
31
+ max_width = max(max(img.width for img in cropped_images), separator_image.width)
32
+ print("Max Width:", max_width)
33
+
34
+ combined_image = Image.new('RGB', (max_width, total_height))
35
+ y = 0
36
+ print(cropped_images, "before combine")
37
+
38
+ for i, img in enumerate(cropped_images):
39
+ combined_image.paste(img, (0, y))
40
+ y += img.height
41
+ if i < len(cropped_images) - 1:
42
+ combined_image.paste(separator_image, (0, y))
43
+ y += separator_height
44
+
45
+ combined_image.save("combinedImage.png")
46
+ return combined_image
47
+
48
+ def preprocess_image(image):
49
+ gray = cv2.cvtColor(np.array(image), cv2.COLOR_BGR2GRAY)
50
+ _, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
51
+ return Image.fromarray(binary)
app/utils/seprator3.png ADDED