-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
282 lines (233 loc) · 8.93 KB
/
Copy pathmain.py
File metadata and controls
282 lines (233 loc) · 8.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
"""
A library to compare images and highlight the differences.
In particular it can be used in tests where the output of a
function is an image.
"""
# #Create a Grid/Matrix of Images
# import PIL, os, glob
# from PIL import Image
# from math import ceil, floor
# PATH = r"C:\Users\path\to\images"
# frame_width = 1920
# images_per_row = 5
# padding = 2
# os.chdir(PATH)
# images = glob.glob("*.png")
# images = images[:30] #get the first 30 images
# img_width, img_height = Image.open(images[0]).size
# sf = (frame_width-(images_per_row-1)*padding)/(images_per_row*img_width)
# #scaling factor
# scaled_img_width = ceil(img_width*sf) #s
# scaled_img_height = ceil(img_height*sf)
# number_of_rows = ceil(len(images)/images_per_row)
# frame_height = ceil(sf*img_height*number_of_rows)
# new_im = Image.new('RGB', (frame_width, frame_height))
# i,j=0,0
# for num, im in enumerate(images):
# if num%images_per_row==0:
# i=0
# im = Image.open(im)
# #Here I resize my opened image, so it is no bigger than 100,100
# im.thumbnail((scaled_img_width,scaled_img_height))
# #Iterate through a 4 by 4 grid with 100 spacing, to place my image
# y_cord = (j//images_per_row)*scaled_img_height
# new_im.paste(im, (i,y_cord))
# print(i, y_cord)
# i=(i+scaled_img_width)+padding
# j+=1
# new_im.show()
# new_im.save("out.jpg", "JPEG", quality=80, optimize=True, progressive=True)
import cv2
import numpy as np
from PIL import Image, ImageDraw
def rescale_image(img_1: Image, img_2: Image):
# Check the image size, two paths from there - resize, check if cropped
width_1, height_1 = img_1.size
width_2, height_2 = img_2.size
width_ratio = width_2 / width_1
height_ratio = height_2 / height_1
if width_ratio != height_ratio:
print("Image is not evenly scaled, perhaps it is cropped or extended.")
if width_ratio == 1 and height_ratio != 1:
print("Only the height has been changed.")
elif width_ratio != 1 and height_ratio == 1:
print("Only the width has been changed.")
else:
print(f"Image 2 has been rescaled by a factor of: {width_ratio}")
return img_2.resize((width_1, height_1))
def check_if_cropped(img_1: np.array, img_2: np.array):
# Find which image is smaller
if img_1.shape[0] <= img_2.shape[0] and img_1.shape[1] <= img_2.shape[1]:
img_cropped = img_1
img_full = img_2
elif img_1.shape[0] >= img_2.shape[0] and img_1.shape[1] >= img_2.shape[1]:
img_cropped = img_2
img_full = img_1
else:
print("Image seems to be reshaped or distorted.")
return None
w, h = img_cropped.shape[:-1]
res = cv2.matchTemplate(img_full, img_cropped, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1], strict=False): # Switch columns and rows
cv2.rectangle(img_full, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
cv2.imwrite("highlight_crop.png", img_full)
if len(loc) > 0:
return True
else:
return False
# img_rgb = cv2.imread("mario.png")
# template = cv2.imread("mario_coin.png")
# w, h = template.shape[:-1]
# res = cv2.matchTemplate(img_rgb, template, cv2.TM_CCOEFF_NORMED)
# threshold = 0.8
# loc = np.where(res >= threshold)
# for pt in zip(*loc[::-1], strict=False): # Switch columns and rows
# cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
# cv2.imwrite("result.png", img_rgb)
def find_difference(img_1: np.array, img_2: np.array):
# Making a blank array in the shape of img_2
out = np.zeros_like(img_2)
# Finding where the difference is
mask = img_1 != img_2
out[mask] = img_2[mask]
# Converting back to image, save & return
out_img = Image.fromarray(out)
out_img.save("differences_1.jpg") # TODO add naming convention
return out_img
def the_algorithm(img_1, img_2, img_1_array, img_2_array):
# Check if the shapes are the same and pixels are identical
if img_1_array.shape == img_2_array.shape and np.all(
img_1_array == img_2_array
):
print("Images are identical!")
return None, ""
elif img_1_array.shape == img_2_array.shape and np.all(
img_1_array != img_2_array
):
print("Difference has been detected. Identifying changes...")
img_diff = find_difference(img_1, img_2)
return img_diff, "The differences have been isolated"
else:
print("""Image has a different shape.
Checking for cropping or reshaping...""")
# If the size is the issue then check if it is cropped
if check_if_cropped(img_1_array, img_2_array):
return None, "The image has been cropped" # check logic here
else:
# If not cropped check if it can rescale
rescaled_img = rescale_image(img_1, img_2)
rescaled_img.save("Rescaled_result.jpg")
# Check if the images now match
if np.all(img_1_array == np.array(rescaled_img)):
print("The image has been successfully rescaled!")
return rescaled_img, "The image had been rescaled"
else:
print("There seems to be a combination manipulation...")
img_diff = find_difference(img_1, img_2)
return (
img_diff,
"""This is a combination manipulation.
\nHere are the isolated differences""",
)
def craft_comparison(
img_1: Image,
img_2: Image,
out_img: Image,
text: str = "",
padding: int = 2,
):
# Get size values
img_1_width, img_1_height = img_1.size
img_2_width, img_2_height = img_2.size
out_img_width, out_img_height = out_img.size
frame_width = (
out_img_width
+ (img_1_width if img_1_width > img_2_width else img_2_width)
+ (3 * padding)
)
frame_height = (
out_img_height
+ (img_1_height if img_1_height > img_2_height else img_2_height)
+ (3 * padding)
)
# Combine images on a blank canvas with padding between
comp_img = Image.new("RGB", (frame_width, frame_height))
comp_img.paste(img_1, (padding, 0))
comp_img.paste(img_2((2 * padding + img_1_width), 0))
output_height = (2 * padding) + (
img_1_height if img_1_height > img_2_height else img_2_height
)
if text == "":
output_width = (frame_width / 2) - (out_img / 2)
else:
# Place image in 4th quadrant of composite image
output_width = frame_width - padding - output_width
# Call draw Method to add 2D graphics in an image
img_draw = ImageDraw.Draw(comp_img)
img_draw.text(
((frame_width / 4), (frame_height * 0.75)), text, fill=(0, 0, 0)
)
comp_img.paste(out_img, (output_width, output_height))
comp_img.save(
"result.png", "png", quality=100, optimize=True, progressive=True
)
return comp_img
# Compare two images pixel by pixel
img_1 = np.array(Image.open("man_with_boxes_1.jpg"))
img_2 = np.array(Image.open("man_with_boxes_alt.jpg"))
# Check if the shapes are the same and pixels are identical
if img_1.shape == img_2.shape and np.all(img_1 == img_2):
print("Images are identical!")
else:
print("Images are different.")
print(img_1.shape)
out = np.zeros_like(img_2)
mask = img_1 != img_2
out[mask] = img_2[mask]
out_img = Image.fromarray(out)
out_img.save("differences_1.jpg")
# Check the image directly, find the differences and
## hightlight them in a side by side comparison
# Include pre check of size, try resizing both to the other size
## PIL library probably best here
# Image may be cropped, move the smaller image around the
## larger one to find a fit (use the OVImage?)
# Compare metadata
# Use the os library and perhaps json?
# Include suggestions for the difference and how to correct for it
# Include a threshold margin of error
def main(img_1_loc, img_2_loc, explanation: bool = True):
# Open the images
img_1 = Image.open(img_1_loc)
img_2 = Image.open(img_2_loc)
# Check if they are identical or not
# Compare two images pixel by pixel
img_1_array = np.array(img_1)
img_2_array = np.array(img_2)
# Run the algorithm on the two images
out_img, comment = the_algorithm(img_1, img_2, img_1_array, img_2_array)
if not explanation:
comment = ""
# Create the comparison image
if out_img is None:
pass
else:
craft_comparison(
img_1,
img_2,
out_img,
comment,
padding=10,
)
# Look at combo changes, e.g. edit and rescale
# Drop threshold in crop check, then apply the diff check to match
# If not find the differences
# Categorise the difference if possible, e.g. text, noise, compressed
# Output composite image with img_1, img_2, img_diff,
## and stats and test results
# TODO: Include test for image compression
# TODO: Test vector images
# TODO: Test for text changes
# TODO: Create standard output showing difference