Spaces:
Building
Building
#==================================================================================# | |
# Find Contours from Image and Convert into PDF # | |
#==================================================================================# | |
import cv2, os | |
import numpy as np | |
from imutils.perspective import four_point_transform | |
from PIL import Image | |
from unstructured.partition.pdf import partition_pdf | |
import json, base64, io | |
from flask import Flask, render_template, flash, redirect, url_for | |
from dotenv import load_dotenv | |
import pytesseract | |
load_dotenv() | |
app = Flask(__name__) | |
app.secret_key = os.getenv("SECRET_KEY") | |
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe" | |
poppler_path=r"C:\poppler-23.11.0\Library\bin" | |
count = 0 | |
OUTPUT_FOLDER = "OUTPUTS" | |
# os.makedirs(OUTPUT_FOLDER, exist_ok=True) | |
IMAGE_FOLDER_PATH = os.path.join(OUTPUT_FOLDER, "SCANNED_IMAGE") | |
# os.makedirs(IMAGE_FOLDER_PATH, exist_ok=True) | |
PDF_FOLDER_PATH = os.path.join(OUTPUT_FOLDER, "SCANNED_PDF") | |
# os.makedirs(PDF_FOLDER_PATH, exist_ok=True) | |
JSON_FOLDER_PATH = os.path.join(OUTPUT_FOLDER, "EXTRACTED_JSON") | |
for path in [OUTPUT_FOLDER, IMAGE_FOLDER_PATH, PDF_FOLDER_PATH, JSON_FOLDER_PATH]: | |
os.makedirs(path, exist_ok=True) | |
# --- FUNCTION: Detect document contour --- | |
def detect_document_contour(image): | |
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) | |
blur = cv2.GaussianBlur(gray, (5, 5), 0) | |
_, thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) | |
contours, _ = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) | |
contours = sorted(contours, key=cv2.contourArea, reverse=True) | |
for contour in contours: | |
area = cv2.contourArea(contour) | |
if area > 1000: | |
peri = cv2.arcLength(contour, True) | |
approx = cv2.approxPolyDP(contour, 0.02 * peri, True) | |
if len(approx) == 4: | |
return approx | |
return None | |
# --- FUNCTION: Extract images from saved PDF --- | |
def extract_images_from_pdf(pdf_path, output_json_path): | |
elements = partition_pdf( | |
filename=pdf_path, | |
strategy="hi_res", | |
extract_image_block_types=["Image"], # or ["Image", "Table"] | |
extract_image_block_to_payload=True, # Set to True to get base64 in output | |
) | |
with open(output_json_path, "w") as f: | |
json.dump([element.to_dict() for element in elements], f, indent=4) | |
# Display extracted images | |
with open(output_json_path, 'r') as file: | |
file_elements = json.load(file) | |
for i, element in enumerate(file_elements): | |
if "image_base64" in element["metadata"]: | |
image_data = base64.b64decode(element["metadata"]["image_base64"]) | |
image = Image.open(io.BytesIO(image_data)) | |
image.show(title=f"Extracted Image {i+1}") | |
# --- Route: Home Page --- | |
def index(): | |
return render_template("index.html") | |
# --- Route: Scan Document --- | |
def scan_document(): | |
global count | |
cap = cv2.VideoCapture(0 + cv2.CAP_DSHOW) | |
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) | |
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) | |
scale = 0.5 | |
contour = None | |
while True: | |
ret, frame = cap.read() | |
if not ret: | |
flash("Camera Error!", "error") | |
break | |
frame = cv2.rotate(frame, cv2.ROTATE_180) | |
display = frame.copy() | |
contour = detect_document_contour(display) | |
if contour is not None: | |
cv2.drawContours(display, [contour], -1, (0, 255, 0), 3) | |
resized = cv2.resize(display, (int(scale * display.shape[1]), int(scale * display.shape[0]))) | |
cv2.imshow("📷 Scan Document - Press 's' to Save, ESC to Exit", resized) | |
key = cv2.waitKey(1) & 0xFF | |
if key == 27: # ESC | |
break | |
elif key == ord('s') and contour is not None: | |
warped = four_point_transform(frame, contour.reshape(4, 2)) | |
image_path = os.path.join(IMAGE_FOLDER_PATH, f"scanned_colored_{count}.jpg") | |
pdf_path = os.path.join(PDF_FOLDER_PATH, f"scanned_colored_{count}.pdf") | |
json_path = os.path.join(JSON_FOLDER_PATH, f"scanned_{count}.json") | |
cv2.imwrite(image_path, warped) | |
img = Image.open(image_path).convert("RGB") | |
img.save(pdf_path) | |
extract_images_from_pdf(pdf_path, json_path) | |
flash("✅ Document scanned and saved!", "success") | |
count += 1 | |
break | |
cap.release() | |
cv2.destroyAllWindows() | |
return redirect(url_for("index")) | |
# --- Run --- | |
if __name__ == "__main__": | |
app.run(host="0.0.0.0", port=7860, debug=False) | |
# while True: | |
# ret, frame = cap.read() | |
# if not ret: | |
# break | |
# frame = cv2.rotate(frame, cv2.ROTATE_180) | |
# display = frame.copy() | |
# contour = detect_document_contour(display) | |
# if contour is not None: | |
# cv2.drawContours(display, [contour], -1, (0, 255, 0), 3) | |
# cv2.imshow("Document Scanner", cv2.resize(display, (int(scale * display.shape[1]), int(scale * display.shape[0])))) | |
# key = cv2.waitKey(1) & 0xFF | |
# if key == 27: # ESC to exit | |
# break | |
# elif key == ord('s') and contour is not None: | |
# warped = four_point_transform(frame, contour.reshape(4, 2)) | |
# image_path = os.path.join(IMAGE_FOLDER_PATH, f"scanned_colored_{count}.jpg") | |
# pdf_path = os.path.join(PDF_FOLDER_PATH,f"scanned_colored_{count}.pdf") | |
# # Save the Image | |
# cv2.imwrite(image_path, warped) | |
# print(f"[INFO] Saved: {image_path}") | |
# # Convert to PDF | |
# img = Image.open(image_path) | |
# img_rgb = img.convert("RGB") | |
# img_rgb.save(pdf_path) | |
# print(f"[INFO] Converted to PDF: {pdf_path}") | |
# # Extract and show embedded images from PDF | |
# print(f"[INFO] Extracting embedded images from PDF...") | |
# # extract_images_from_pdf(pdf_path, JSON_FOLDER_PATH) | |
# count += 1 | |
# cap.release() | |
# cv2.destroyAllWindows() | |
''' Simple version Not a Flask APP ''' | |
# import cv2, os, json, base64, io | |
# import numpy as np | |
# from imutils.perspective import four_point_transform | |
# from PIL import Image | |
# from unstructured.partition.pdf import partition_pdf | |
# import pytesseract | |
# # --- PATH CONFIGURATION --- | |
# pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe" | |
# POPPLER_PATH = r"C:\poppler-23.11.0\Library\bin" | |
# OUTPUT_FOLDER = "OUTPUTS" | |
# IMAGE_FOLDER_PATH = os.path.join(OUTPUT_FOLDER, "SCANNED_IMAGE") | |
# PDF_FOLDER_PATH = os.path.join(OUTPUT_FOLDER, "SCANNED_PDF") | |
# JSON_OUTPUT_FOLDER = os.path.join(OUTPUT_FOLDER, "EXTRACTED_JSON") | |
# for path in [OUTPUT_FOLDER, IMAGE_FOLDER_PATH, PDF_FOLDER_PATH, JSON_OUTPUT_FOLDER]: | |
# os.makedirs(path, exist_ok=True) | |
# # --- FUNCTION: Detect document contour --- | |
# def detect_document_contour(image): | |
# gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) | |
# blur = cv2.GaussianBlur(gray, (5, 5), 0) | |
# _, thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) | |
# contours, _ = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) | |
# contours = sorted(contours, key=cv2.contourArea, reverse=True) | |
# for contour in contours: | |
# area = cv2.contourArea(contour) | |
# if area > 1000: | |
# peri = cv2.arcLength(contour, True) | |
# approx = cv2.approxPolyDP(contour, 0.02 * peri, True) | |
# if len(approx) == 4: | |
# return approx | |
# return None | |
# # --- FUNCTION: Extract images from saved PDF --- | |
# def extract_images_from_pdf(pdf_path, output_json_path): | |
# elements = partition_pdf( | |
# filename=pdf_path, | |
# poppler_path=POPPLER_PATH, | |
# strategy="hi_res", | |
# extract_image_block_types=["Image"], | |
# extract_image_block_to_payload=True, | |
# ) | |
# with open(output_json_path, "w") as f: | |
# json.dump([element.to_dict() for element in elements], f, indent=4) | |
# # Display extracted images | |
# with open(output_json_path, 'r') as file: | |
# file_elements = json.load(file) | |
# for i, element in enumerate(file_elements): | |
# if "image_base64" in element["metadata"]: | |
# image_data = base64.b64decode(element["metadata"]["image_base64"]) | |
# image = Image.open(io.BytesIO(image_data)) | |
# image.show(title=f"Extracted Image {i+1}") | |
# # --- WEBCAM SCANNER START --- | |
# # cap = cv2.VideoCapture(0 + cv2.CAP_DSHOW) | |
# cap = cv2.VideoCapture("http://100.71.6.36:8080/video") | |
# cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) | |
# cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) | |
# scale = 0.5 | |
# count = 0 | |
# while True: | |
# ret, frame = cap.read() | |
# if not ret: | |
# break | |
# frame = cv2.rotate(frame, cv2.ROTATE_180) | |
# display = frame.copy() | |
# contour = detect_document_contour(display) | |
# if contour is not None: | |
# cv2.drawContours(display, [contour], -1, (0, 255, 0), 3) | |
# cv2.imshow("Document Scanner", cv2.resize(display, (int(scale * display.shape[1]), int(scale * display.shape[0])))) | |
# key = cv2.waitKey(1) & 0xFF | |
# if key == 27: # ESC to exit | |
# break | |
# elif key == ord('s') and contour is not None: | |
# warped = four_point_transform(frame, contour.reshape(4, 2)) | |
# image_path = os.path.join(IMAGE_FOLDER_PATH, f"scanned_colored_{count}.jpg") | |
# pdf_path = os.path.join(PDF_FOLDER_PATH, f"scanned_colored_{count}.pdf") | |
# json_path = os.path.join(JSON_OUTPUT_FOLDER, f"embedded_images_{count}.json") | |
# # Save Image | |
# cv2.imwrite(image_path, warped) | |
# print(f"[INFO] Saved image: {image_path}") | |
# # Convert to PDF | |
# img = Image.open(image_path) | |
# img_rgb = img.convert("RGB") | |
# img_rgb.save(pdf_path) | |
# print(f"[INFO] Converted to PDF: {pdf_path}") | |
# # Extract and show embedded images from PDF | |
# print(f"[INFO] Extracting embedded images from PDF...") | |
# extract_images_from_pdf(pdf_path, json_path) | |
# count += 1 | |
# cap.release() | |
# cv2.destroyAllWindows() | |
''' | |
#==================================================================================# | |
# Extract Images from PDF # | |
#==================================================================================# | |
from unstructured.partition.pdf import partition_pdf | |
import pytesseract | |
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe" | |
elements = partition_pdf( | |
filename=r"E:\Pratham\2025\Harsh Sir\Scratch Vision\images\page1.pdf", | |
poppler_path=r"C:\poppler-23.11.0\Library\bin", | |
strategy="hi_res", | |
extract_image_block_types=["Image"], # or ["Image", "Table"] | |
extract_image_block_to_payload=True, # Set to True to get base64 in output | |
) | |
import json, base64, io, os | |
from PIL import Image | |
# Save JSON output | |
os.makedirs("output", exist_ok=True) | |
with open("output/embedded-images-tables.json", "w") as f: | |
json.dump([element.to_dict() for element in elements], f, indent=4) | |
def get_image_block_types(input_json_file_path: str): | |
with open(input_json_file_path, 'r') as file: | |
file_elements = json.load(file) | |
for element in file_elements: | |
if "image_base64" in element["metadata"]: | |
image_data = base64.b64decode(element["metadata"]["image_base64"]) | |
image = Image.open(io.BytesIO(image_data)) | |
image.show() | |
# Example usage: | |
get_image_block_types("output/embedded-images-tables.json")''' | |
# from unstructured_client import UnstructuredClient | |
# from unstructured_client.models import operations, shared | |
# from unstructured.staging.base import elements_from_dicts, elements_to_json | |
# import os | |
# import base64 | |
# from PIL import Image | |
# import io | |
# if __name__ == "__main__": | |
# client = UnstructuredClient( | |
# api_key_auth=os.getenv("UNSTRUCTURED_API_KEY") | |
# ) | |
# # Path to your PDF file | |
# local_input_filepath = "your-pdf-file.pdf" | |
# local_output_filepath = "output.json" | |
# with open(local_input_filepath, "rb") as f: | |
# files = shared.Files( | |
# content=f.read(), | |
# file_name=local_input_filepath | |
# ) | |
# request = operations.PartitionRequest( | |
# shared.PartitionParameters( | |
# files=files, | |
# split_pdf_page=True, | |
# split_pdf_allow_failed=True, | |
# split_pdf_concurrency_level=15, | |
# # Extract Base64-encoded images and tables | |
# extract_image_block_types=["Image", "Table"] | |
# ) | |
# ) | |
# try: | |
# result = client.general.partition(request=request) | |
# for element in result.elements: | |
# if "image_base64" in element["metadata"]: | |
# # Decode and display the image | |
# image_data = base64.b64decode(element["metadata"]["image_base64"]) | |
# image = Image.open(io.BytesIO(image_data)) | |
# image.show() # This will open the image | |
# # Save results as JSON | |
# dict_elements = elements_from_dicts(element_dicts=result.elements) | |
# elements_to_json( | |
# elements=dict_elements, | |
# indent=2, | |
# filename=local_output_filepath | |
# ) | |
# except Exception as e: | |
# print(e) | |
# -------------------------------------------------------------------------------------- # | |
# # STEP 1 | |
# # import libraries | |
# import fitz # PyMuPDF | |
# import io | |
# from PIL import Image | |
# # STEP 2 | |
# # file path you want to extract images from | |
# file = r"E:\Pratham\2025\Harsh Sir\Scratch Vision\images/page1_orig.pdf" | |
# # open the file | |
# pdf_file = fitz.open(file) | |
# # STEP 3 | |
# # iterate over PDF pages | |
# for page_index in range(len(pdf_file)): | |
# # get the page itself | |
# page = pdf_file.load_page(page_index) # load the page | |
# image_list = page.get_images(full=True) # get images on the page | |
# # printing number of images found in this page | |
# if image_list: | |
# print(f"[+] Found a total of {len(image_list)} images on page {page_index}") | |
# else: | |
# print("[!] No images found on page", page_index) | |
# for image_index, img in enumerate(image_list, start=1): | |
# # get the XREF of the image | |
# xref = img[0] | |
# # extract the image bytes | |
# base_image = pdf_file.extract_image(xref) | |
# image_bytes = base_image["image"] | |
# # get the image extension | |
# image_ext = base_image["ext"] | |
# # save the image | |
# image_name = f"image{page_index+1}_{image_index}.{image_ext}" | |
# with open(image_name, "wb") as image_file: | |
# image_file.write(image_bytes) | |
# print(f"[+] Image saved as {image_name}") | |
# -------------------------------------------------------------------------------------- # | |
# from pdf2image import convert_from_path | |
# import numpy as np | |
# import cv2 | |
# def extract_grid_cells_from_pdf(pdf_path, prefix="sub"): | |
# # Convert PDF's first page to image | |
# pages = convert_from_path( | |
# pdf_path, | |
# dpi=300, | |
# poppler_path=r"C:\poppler-23.11.0\Library\bin" | |
# ) | |
# pil = pages[0] | |
# img = np.array(pil)[:, :, ::-1] # RGB→BGR | |
# gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
# _, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV) | |
# kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) | |
# dil = cv2.dilate(thresh, kernel, iterations=2) | |
# cnts, _ = cv2.findContours(dil, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
# cells = [cv2.boundingRect(c) for c in cnts if cv2.contourArea(c) > 1000] | |
# cells = sorted(cells, key=lambda r: (r[1], r[0])) | |
# for i, (x, y, w, h) in enumerate(cells): | |
# crop = img[y:y+h, x:x+w] | |
# cv2.imwrite(f"{prefix}_{i:02d}.png", crop) | |
# print("Saved", f"{prefix}_{i:02d}.png") | |
# if __name__ == "__main__": | |
# extract_grid_cells_from_pdf( | |
# r"E:\Pratham\2025\Harsh Sir\Scratch Vision\images\page1_orig.pdf" | |
# ) | |
# import cv2 | |
# import layoutparser as lp | |
# from pdf2image import convert_from_path | |
# from reportlab.pdfgen import canvas | |
# from reportlab.lib.pagesizes import letter | |
# import numpy as np | |
# import tempfile | |
# import os | |
# # 1️⃣ Setup LayoutParser model | |
# model = lp.Detectron2LayoutModel( | |
# "lp://PrimaLayout/PrimaLayout/mask_rcnn_R_50_FPN_3x/config", | |
# label_map={0: "Text", 1: "Title", 2: "List", 3: "Table", 4: "Figure"} | |
# ) | |
# # 2️⃣ Utility to crop and save a layout region | |
# def crop_and_save(img, block, out_dir, idx): | |
# x1, y1, x2, y2 = map(int, block.block.x_1_y_2_x_2_y_2) | |
# cropped = img[y1:y2, x1:x2] | |
# path = os.path.join(out_dir, f"crop_{idx}.png") | |
# cv2.imwrite(path, cropped) | |
# return path | |
# # 3️⃣ Convert cropped images into multi-page PDF | |
# def imgs_to_pdf(img_paths, output_pdf): | |
# c = canvas.Canvas(output_pdf, pagesize=letter) | |
# w, h = letter | |
# for img in img_paths: | |
# c.drawImage(img, 0, 0, width=w, height=h) | |
# c.showPage() | |
# c.save() | |
# # 4️⃣ If user input is a PDF or image folder | |
# def process_document(pdf_path, output_pdf): | |
# imgs = convert_from_path(pdf_path) | |
# cropped_paths = [] | |
# with tempfile.TemporaryDirectory() as tmp: | |
# for page_idx, pil_im in enumerate(imgs): | |
# img = cv2.cvtColor(np.array(pil_im), cv2.COLOR_RGB2BGR) | |
# layout = model.detect(img) | |
# for idx, block in enumerate(layout): | |
# path = crop_and_save(img, block, tmp, f"{page_idx}_{idx}") | |
# cropped_paths.append(path) | |
# imgs_to_pdf(cropped_paths, output_pdf) | |
# # 5️⃣ Real-time camera/video feed | |
# def process_video(output_pdf, src=0, frame_limit=100): | |
# cap = cv2.VideoCapture(src) | |
# idx = 0 | |
# cropped_paths = [] | |
# with tempfile.TemporaryDirectory() as tmp: | |
# while idx < frame_limit: | |
# ret, img = cap.read() | |
# if not ret: | |
# break | |
# layout = model.detect(img) | |
# for i, block in enumerate(layout): | |
# path = crop_and_save(img, block, tmp, f"{idx}_{i}") | |
# cropped_paths.append(path) | |
# idx += 1 | |
# cap.release() | |
# imgs_to_pdf(cropped_paths, output_pdf) | |
# if __name__ == "__main__": | |
# import argparse | |
# ap = argparse.ArgumentParser() | |
# ap.add_argument("--input", required=True, | |
# help="path to PDF or 'cam' for camera") | |
# ap.add_argument("--output", required=True, help="output PDF path") | |
# ap.add_argument("--frames", type=int, default=50, | |
# help="frames to scan if using camera") | |
# args = ap.parse_args() | |
# if args.input.lower().endswith(".pdf"): | |
# process_document(args.input, args.output) | |
# elif args.input.lower() == "cam": | |
# process_video(args.output, src=0, frame_limit=args.frames) | |
# else: | |
# print("Unsupported input. Use PDF path or 'cam'.") | |
# import cv2 | |
# from PIL import Image | |
# import numpy as np | |
# def get_contours(frame): | |
# gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) | |
# # Threshold to binary | |
# _, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV) | |
# # Find contours | |
# contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
# return contours | |
# def extract_regions(frame, contours): | |
# rois = [] | |
# for cnt in contours: | |
# x, y, w, h = cv2.boundingRect(cnt) | |
# if w*h < 1000: # skip small noise | |
# continue | |
# roi = frame[y:y+h, x:x+w] | |
# rois.append(roi) | |
# return rois | |
# def save_rois_as_pdf(rois, output_path): | |
# pil_imgs = [] | |
# for roi in rois: | |
# rgb = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB) | |
# pil = Image.fromarray(rgb) | |
# pil_imgs.append(pil) | |
# if pil_imgs: | |
# pil_imgs[0].save(output_path, save_all=True, append_images=pil_imgs[1:]) | |
# print(f"Saved {len(pil_imgs)} regions to {output_path}") | |
# def main(): | |
# cap = cv2.VideoCapture(0) | |
# all_rois = [] | |
# print("Press 'c' to capture and extract; 'q' to quit.") | |
# while True: | |
# ret, frame = cap.read() | |
# if not ret: | |
# break | |
# cv2.imshow("Live Feed", frame) | |
# key = cv2.waitKey(1) & 0xFF | |
# if key == ord('c'): | |
# contours = get_contours(frame) | |
# rois = extract_regions(frame, contours) | |
# all_rois.extend(rois) | |
# print(f"Captured {len(rois)} regions.") | |
# elif key == ord('q'): | |
# break | |
# cap.release() | |
# cv2.destroyAllWindows() | |
# if all_rois: | |
# save_rois_as_pdf(all_rois, "output_contours.pdf") | |
# else: | |
# print("No regions captured.") | |
# if __name__ == "__main__": | |
# main() | |
# import cv2 | |
# from PIL import Image | |
# import numpy as np | |
# def get_edge_contours(frame, low=50, high=150): | |
# gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) | |
# blurred = cv2.GaussianBlur(gray, (5, 5), 1.0) | |
# edges = cv2.Canny(blurred, low, high) | |
# contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
# return contours, edges | |
# def extract_edge_rois(frame, contours, min_area=1000): | |
# rois = [] | |
# for cnt in contours: | |
# x, y, w, h = cv2.boundingRect(cnt) | |
# if w * h < min_area: | |
# continue | |
# roi = frame[y:y+h, x:x+w] | |
# rois.append(roi) | |
# return rois | |
# def save_rois_as_pdf(rois, output_path): | |
# pil_imgs = [] | |
# for roi in rois: | |
# rgb = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB) | |
# pil_imgs.append(Image.fromarray(rgb)) | |
# if pil_imgs: | |
# pil_imgs[0].save(output_path, save_all=True, append_images=pil_imgs[1:]) | |
# print(f"✅ Saved {len(pil_imgs)} edge-region(s) to {output_path}") | |
# else: | |
# print("⚠️ No edge-based regions detected—PDF not created.") | |
# def main(): | |
# cap = cv2.VideoCapture(0) | |
# all_rois = [] | |
# print("Press ‘c’ to capture current edge regions, ‘q’ to quit.") | |
# while True: | |
# ret, frame = cap.read() | |
# if not ret: | |
# break | |
# contours, edges = get_edge_contours(frame) | |
# cv2.imshow("Live Feed", frame) | |
# cv2.imshow("Edges", edges) | |
# key = cv2.waitKey(1) & 0xFF | |
# if key == ord('c'): | |
# rois = extract_edge_rois(frame, contours) | |
# all_rois.extend(rois) | |
# print(f"🔄 Captured {len(rois)} edge-region(s). Total: {len(all_rois)}") | |
# elif key == ord('q'): | |
# break | |
# cap.release() | |
# cv2.destroyAllWindows() | |
# if all_rois: | |
# save_rois_as_pdf(all_rois, "edge_contours.pdf") | |
# else: | |
# print("❌ No regions captured.") | |
# if __name__ == "__main__": | |
# main() | |