SathvikGanta commited on
Commit
03871ff
·
verified ·
1 Parent(s): 4212f18

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -83
app.py CHANGED
@@ -34,9 +34,9 @@ def align_images(img1, img2):
34
  aligned_img = cv2.warpPerspective(img2, matrix, (img1.shape[1], img1.shape[0]))
35
  return aligned_img
36
 
37
- # Compare images for visual changes
38
- def compare_images(img1, img2):
39
- diff = cv2.absdiff(img1, img2)
40
  gray_diff = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
41
 
42
  # Apply Gaussian blur to reduce noise
@@ -45,124 +45,107 @@ def compare_images(img1, img2):
45
  # Apply thresholding
46
  _, thresh = cv2.threshold(blurred_diff, 40, 255, cv2.THRESH_BINARY)
47
 
48
- # Morphological operations to smooth out noise
49
  kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
50
  cleaned = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
51
 
52
- return cleaned
53
-
54
- # Compare text and generate differences
55
- def compare_text(orig_text, edit_text, start_position):
56
- diff = difflib.ndiff(orig_text.splitlines(), edit_text.splitlines())
57
- text_changes = []
58
- position_counter = start_position
59
- for line in diff:
60
- if line.startswith("+ "): # Added text
61
- text_changes.append((position_counter, f'"{line[2:]}" added at {position_counter}'))
62
- elif line.startswith("- "): # Removed text
63
- text_changes.append((position_counter, f'"{line[2:]}" removed at {position_counter}'))
64
- position_counter += 1
65
- return text_changes, position_counter
66
-
67
- # Highlight visual changes
68
- def highlight_visual_changes(img1, img2, mask, start_position):
69
- overlay = img2.copy()
70
- contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
71
  visual_changes = []
 
72
  font = cv2.FONT_HERSHEY_SIMPLEX
73
  font_scale = 0.8
74
  thickness = 2
75
- position_counter = start_position
76
 
77
  for cnt in contours:
78
- if cv2.contourArea(cnt) > 100: # Filter based on area to reduce false positives
79
  x, y, w, h = cv2.boundingRect(cnt)
80
- cv2.rectangle(overlay, (x, y), (x + w, y + h), (0, 0, 255), 2) # Red for changes
81
  cv2.putText(overlay, str(position_counter), (x, y - 10), font, font_scale, (0, 255, 0), thickness)
82
  visual_changes.append((position_counter, f'Visual change detected at position {position_counter}'))
83
  position_counter += 1
84
 
85
  return overlay, visual_changes, position_counter
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  # Sanitize text for PDF compatibility
88
  def sanitize_text(text):
89
- """Sanitize text for FPDF by replacing unsupported characters."""
90
  return text.encode('latin-1', errors='replace').decode('latin-1')
91
 
92
- # Generate visual changes report
93
- def generate_visual_report(original_images, edited_images, combined_images, visual_changes):
94
- output_path = "outputs/visual_changes.pdf"
95
- pdf_visual = FPDF()
96
- for img in combined_images:
97
- temp_path = "temp_image_visual.png"
98
  cv2.imwrite(temp_path, img)
99
- pdf_visual.add_page()
100
- pdf_visual.image(temp_path, x=10, y=10, w=190)
101
  os.remove(temp_path)
102
- pdf_visual.add_page()
103
- pdf_visual.set_font("Arial", size=12)
104
- pdf_visual.cell(0, 10, "Visual Changes", ln=True, align="C")
105
- pdf_visual.ln(10)
106
- for _, change in visual_changes:
107
- pdf_visual.cell(0, 10, sanitize_text(change), ln=True)
108
- pdf_visual.output(output_path)
109
- return output_path
110
 
111
- # Generate text changes report
112
- def generate_text_report(original_images, edited_images, combined_images, text_changes):
113
- output_path = "outputs/text_changes.pdf"
114
- pdf_text = FPDF()
115
- for img in combined_images:
116
- temp_path = "temp_image_text.png"
117
- cv2.imwrite(temp_path, img)
118
- pdf_text.add_page()
119
- pdf_text.image(temp_path, x=10, y=10, w=190)
120
- os.remove(temp_path)
121
- pdf_text.add_page()
122
- pdf_text.set_font("Arial", size=12)
123
- pdf_text.cell(0, 10, "Text Changes", ln=True, align="C")
124
- pdf_text.ln(10)
125
- for _, change in text_changes:
126
- pdf_text.cell(0, 10, sanitize_text(change), ln=True)
127
- pdf_text.output(output_path)
128
  return output_path
129
 
130
- # Generate separate PDFs for visual and text changes
131
  def generate_separate_comparisons(original_pdf, edited_pdf):
132
  original_images = convert_pdf_to_images(original_pdf)
133
  edited_images = convert_pdf_to_images(edited_pdf)
134
- combined_images = []
 
 
135
  visual_changes = []
136
- text_changes = []
137
  position_counter = 1
138
-
139
  for orig_img, edit_img in zip(original_images, edited_images):
140
  aligned_img = align_images(orig_img, edit_img)
141
-
142
- # Visual comparison
143
- diff_mask = compare_images(orig_img, aligned_img)
144
- highlighted_img, page_visual_changes, position_counter = highlight_visual_changes(
145
- orig_img, edit_img, diff_mask, position_counter
146
  )
147
  visual_changes.extend(page_visual_changes)
 
148
 
149
- # Text comparison
150
- orig_text = pytesseract.image_to_string(orig_img)
151
- edit_text = pytesseract.image_to_string(edit_img)
152
- page_text_changes, position_counter = compare_text(orig_text, edit_text, position_counter)
153
- text_changes.extend(page_text_changes)
154
 
155
- # Combine images for side-by-side display
156
- height = min(orig_img.shape[0], highlighted_img.shape[0])
157
- orig_img_resized = orig_img[:height]
158
- highlighted_img_resized = highlighted_img[:height]
159
- combined_images.append(np.hstack((orig_img_resized, highlighted_img_resized)))
 
 
 
 
160
 
161
- # Generate separate reports
162
- visual_report = generate_visual_report(original_images, edited_images, combined_images, visual_changes)
163
- text_report = generate_text_report(original_images, edited_images, combined_images, text_changes)
 
164
 
165
- return visual_report, text_report
166
 
167
  # Gradio interface function
168
  def pdf_comparison(original_pdf, edited_pdf):
 
34
  aligned_img = cv2.warpPerspective(img2, matrix, (img1.shape[1], img1.shape[0]))
35
  return aligned_img
36
 
37
+ # Perform pixel-based comparison for visual changes
38
+ def compare_visual_changes(orig_img, edit_img, start_position):
39
+ diff = cv2.absdiff(orig_img, edit_img)
40
  gray_diff = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
41
 
42
  # Apply Gaussian blur to reduce noise
 
45
  # Apply thresholding
46
  _, thresh = cv2.threshold(blurred_diff, 40, 255, cv2.THRESH_BINARY)
47
 
48
+ # Morphological operations to clean noise
49
  kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
50
  cleaned = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
51
 
52
+ contours, _ = cv2.findContours(cleaned, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
53
+ overlay = edit_img.copy()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  visual_changes = []
55
+ position_counter = start_position
56
  font = cv2.FONT_HERSHEY_SIMPLEX
57
  font_scale = 0.8
58
  thickness = 2
 
59
 
60
  for cnt in contours:
61
+ if cv2.contourArea(cnt) > 100: # Filter out small regions
62
  x, y, w, h = cv2.boundingRect(cnt)
63
+ cv2.rectangle(overlay, (x, y), (x + w, y + h), (0, 0, 255), 2) # Red bounding box
64
  cv2.putText(overlay, str(position_counter), (x, y - 10), font, font_scale, (0, 255, 0), thickness)
65
  visual_changes.append((position_counter, f'Visual change detected at position {position_counter}'))
66
  position_counter += 1
67
 
68
  return overlay, visual_changes, position_counter
69
 
70
+ # Perform OCR-based comparison for text changes
71
+ def compare_text_changes(orig_img, edit_img, start_position):
72
+ orig_text = pytesseract.image_to_string(orig_img)
73
+ edit_text = pytesseract.image_to_string(edit_img)
74
+ diff = difflib.ndiff(orig_text.splitlines(), edit_text.splitlines())
75
+ text_changes = []
76
+ position_counter = start_position
77
+
78
+ for line in diff:
79
+ if line.startswith("+ "): # Added text
80
+ text_changes.append((position_counter, f'"{line[2:]}" added at position {position_counter}'))
81
+ elif line.startswith("- "): # Removed text
82
+ text_changes.append((position_counter, f'"{line[2:]}" removed at position {position_counter}'))
83
+ position_counter += 1
84
+
85
+ return text_changes, position_counter
86
+
87
  # Sanitize text for PDF compatibility
88
  def sanitize_text(text):
 
89
  return text.encode('latin-1', errors='replace').decode('latin-1')
90
 
91
+ # Generate PDF report
92
+ def generate_report(images, changes, title, output_path):
93
+ pdf = FPDF()
94
+ for img in images:
95
+ temp_path = "temp_image.png"
 
96
  cv2.imwrite(temp_path, img)
97
+ pdf.add_page()
98
+ pdf.image(temp_path, x=10, y=10, w=190)
99
  os.remove(temp_path)
 
 
 
 
 
 
 
 
100
 
101
+ pdf.add_page()
102
+ pdf.set_font("Arial", size=12)
103
+ pdf.cell(0, 10, sanitize_text(title), ln=True, align="C")
104
+ pdf.ln(10)
105
+ for _, change in changes:
106
+ pdf.cell(0, 10, sanitize_text(change), ln=True)
107
+
108
+ pdf.output(output_path)
 
 
 
 
 
 
 
 
 
109
  return output_path
110
 
111
+ # Perform visual and text comparisons separately
112
  def generate_separate_comparisons(original_pdf, edited_pdf):
113
  original_images = convert_pdf_to_images(original_pdf)
114
  edited_images = convert_pdf_to_images(edited_pdf)
115
+
116
+ # Visual comparison
117
+ visual_combined_images = []
118
  visual_changes = []
 
119
  position_counter = 1
 
120
  for orig_img, edit_img in zip(original_images, edited_images):
121
  aligned_img = align_images(orig_img, edit_img)
122
+ highlighted_img, page_visual_changes, position_counter = compare_visual_changes(
123
+ orig_img, aligned_img, position_counter
 
 
 
124
  )
125
  visual_changes.extend(page_visual_changes)
126
+ visual_combined_images.append(np.hstack((orig_img, highlighted_img)))
127
 
128
+ # Generate visual changes report
129
+ visual_report_path = generate_report(
130
+ visual_combined_images, visual_changes, "Visual Changes", "outputs/visual_changes.pdf"
131
+ )
 
132
 
133
+ # Text comparison
134
+ text_combined_images = []
135
+ text_changes = []
136
+ position_counter = 1
137
+ for orig_img, edit_img in zip(original_images, edited_images):
138
+ aligned_img = align_images(orig_img, edit_img)
139
+ page_text_changes, position_counter = compare_text_changes(orig_img, aligned_img, position_counter)
140
+ text_changes.extend(page_text_changes)
141
+ text_combined_images.append(np.hstack((orig_img, aligned_img)))
142
 
143
+ # Generate text changes report
144
+ text_report_path = generate_report(
145
+ text_combined_images, text_changes, "Text Changes", "outputs/text_changes.pdf"
146
+ )
147
 
148
+ return visual_report_path, text_report_path
149
 
150
  # Gradio interface function
151
  def pdf_comparison(original_pdf, edited_pdf):