update,
This commit is contained in:
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/beach.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/beach.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/building.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/building.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/bus.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/bus.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
162
vinniesniper-54816/task1/_ref/2022-Codes-Python/demo.py
Normal file
162
vinniesniper-54816/task1/_ref/2022-Codes-Python/demo.py
Normal file
@@ -0,0 +1,162 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
from glob import glob
|
||||
|
||||
# the directory of the image database
|
||||
database_dir = "image.orig"
|
||||
|
||||
# Compute pixel-by-pixel difference and return the sum
|
||||
def compareImgs(img1, img2):
|
||||
# resize img2 to img1
|
||||
img2 = cv.resize(img2, (img1.shape[1], img1.shape[0]))
|
||||
diff = cv.absdiff(img1, img2)
|
||||
return diff.sum()
|
||||
|
||||
def compareImgs_hist(img1, img2):
|
||||
width, height = img1.shape[1], img1.shape[0]
|
||||
img2 = cv.resize(img2, (width, height))
|
||||
num_bins = 10
|
||||
hist1 = [0] * num_bins
|
||||
hist2 = [0] * num_bins
|
||||
bin_width = 255.0 / num_bins + 1e-4
|
||||
# compute histogram from scratch
|
||||
|
||||
# for w in range(width):
|
||||
# for h in range(height):
|
||||
# hist1[int(img1[h, w] / bin_width)] += 1
|
||||
# hist2[int(img2[h, w] / bin_width)] += 1
|
||||
|
||||
# compute histogram by using opencv function
|
||||
# https://docs.opencv.org/4.x/d6/dc7/group__imgproc__hist.html#ga4b2b5fd75503ff9e6844cc4dcdaed35d
|
||||
|
||||
hist1 = cv.calcHist([img1], [0], None, [num_bins], [0, 255])
|
||||
hist2 = cv.calcHist([img2], [0], None, [num_bins], [0, 255])
|
||||
sum = 0
|
||||
for i in range(num_bins):
|
||||
sum += abs(hist1[i] - hist2[i])
|
||||
return sum / float(width * height)
|
||||
|
||||
def retrieval():
|
||||
print("1: beach")
|
||||
print("2: building")
|
||||
print("3: bus")
|
||||
print("4: dinosaur")
|
||||
print("5: flower")
|
||||
print("6: horse")
|
||||
print("7: man")
|
||||
choice = input("Type in the number to choose a category and type enter to confirm\n")
|
||||
if choice == '1':
|
||||
src_input = cv.imread("beach.jpg")
|
||||
print("You choose: %s - beach\n" % choice)
|
||||
if choice == '2':
|
||||
src_input = cv.imread("building.jpg")
|
||||
print("You choose: %s - building\n" % choice)
|
||||
if choice == '3':
|
||||
src_input = cv.imread("bus.jpg")
|
||||
print("You choose: %s - bus\n" % choice)
|
||||
if choice == '4':
|
||||
src_input = cv.imread("dinosaur.jpg")
|
||||
print("You choose: %s - dinosaur\n" % choice)
|
||||
if choice == '5':
|
||||
src_input = cv.imread("flower.jpg")
|
||||
print("You choose: %s - flower\n" % choice)
|
||||
if choice == '6':
|
||||
src_input = cv.imread("horse.jpg")
|
||||
print("You choose: %s - horse\n" % choice)
|
||||
if choice == '7':
|
||||
src_input = cv.imread("man.jpg")
|
||||
print("You choose: %s - man\n" % choice)
|
||||
|
||||
min_diff = 1e50
|
||||
|
||||
# src_input = cv.imread("man.jpg")
|
||||
cv.imshow("Input", src_input)
|
||||
|
||||
# change the image to gray scale
|
||||
src_gray = cv.cvtColor(src_input, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# read image database
|
||||
database = sorted(glob(database_dir + "/*.jpg"))
|
||||
|
||||
for img in database:
|
||||
# read image
|
||||
img_rgb = cv.imread(img)
|
||||
# convert to gray scale
|
||||
img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
|
||||
# compare the two images
|
||||
diff = compareImgs(src_gray, img_gray)
|
||||
# compare the two images by histogram, uncomment the following line to use histogram
|
||||
# diff = compareImgs_hist(src_gray, img_gray)
|
||||
print(img, diff)
|
||||
# find the minimum difference
|
||||
if diff <= min_diff:
|
||||
# update the minimum difference
|
||||
min_diff = diff
|
||||
# update the most similar image
|
||||
closest_img = img_rgb
|
||||
result = img
|
||||
|
||||
print("the most similar image is %s, the pixel-by-pixel difference is %f " % (result, min_diff))
|
||||
print("\n")
|
||||
|
||||
cv.imshow("Result", closest_img)
|
||||
cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
|
||||
def SIFT():
|
||||
img1 = cv.imread("flower.jpg")
|
||||
img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print('Error loading images!')
|
||||
exit(0)
|
||||
#-- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
#-- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
#-- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
#-- Show detected matches
|
||||
cv.imshow('Matches: SIFT (Python)', img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key = lambda x:x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x:x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
#-- Show detected matches
|
||||
cv.imshow('Good Matches: SIFT (Python)', img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
|
||||
def main():
|
||||
# img = cv.imread("beach.jpg")
|
||||
# cv.imshow("Image", img)
|
||||
# from matplotlib import pyplot as plt
|
||||
# plt.hist(img.ravel(),10,[0,256]); plt.show()
|
||||
# gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
||||
# cv.imshow("Gray Image", gray_img)
|
||||
# cv.waitKey()
|
||||
|
||||
|
||||
print("1: Image retrieval demo")
|
||||
print("2: SIFT demo")
|
||||
number = int(input("Type in the number to choose a demo and type enter to confirm\n"))
|
||||
if number == 1:
|
||||
retrieval()
|
||||
elif number == 2:
|
||||
SIFT()
|
||||
# pass
|
||||
else:
|
||||
print("Invalid input")
|
||||
exit()
|
||||
|
||||
main()
|
260
vinniesniper-54816/task1/_ref/2022-Codes-Python/demo_draft1.py
Normal file
260
vinniesniper-54816/task1/_ref/2022-Codes-Python/demo_draft1.py
Normal file
@@ -0,0 +1,260 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
from glob import glob
|
||||
import os,sys
|
||||
from pprint import pprint
|
||||
|
||||
# the directory of the image database
|
||||
database_dir = "image.orig"
|
||||
|
||||
# Compute pixel-by-pixel difference and return the sum
|
||||
def compareImgs(img1, img2):
|
||||
# resize img2 to img1
|
||||
img2 = cv.resize(img2, (img1.shape[1], img1.shape[0]))
|
||||
diff = cv.absdiff(img1, img2)
|
||||
return diff.sum()
|
||||
|
||||
def compareImgs_hist(img1, img2):
|
||||
width, height = img1.shape[1], img1.shape[0]
|
||||
img2 = cv.resize(img2, (width, height))
|
||||
num_bins = 10
|
||||
hist1 = [0] * num_bins
|
||||
hist2 = [0] * num_bins
|
||||
bin_width = 255.0 / num_bins + 1e-4
|
||||
# compute histogram from scratch
|
||||
|
||||
# for w in range(width):
|
||||
# for h in range(height):
|
||||
# hist1[int(img1[h, w] / bin_width)] += 1
|
||||
# hist2[int(img2[h, w] / bin_width)] += 1
|
||||
|
||||
# compute histogram by using opencv function
|
||||
# https://docs.opencv.org/4.x/d6/dc7/group__imgproc__hist.html#ga4b2b5fd75503ff9e6844cc4dcdaed35d
|
||||
|
||||
hist1 = cv.calcHist([img1], [0], None, [num_bins], [0, 255])
|
||||
hist2 = cv.calcHist([img2], [0], None, [num_bins], [0, 255])
|
||||
sum = 0
|
||||
for i in range(num_bins):
|
||||
sum += abs(hist1[i] - hist2[i])
|
||||
return sum / float(width * height)
|
||||
|
||||
def retrieval():
|
||||
print("1: beach")
|
||||
print("2: building")
|
||||
print("3: bus")
|
||||
print("4: dinosaur")
|
||||
print("5: flower")
|
||||
print("6: horse")
|
||||
print("7: man")
|
||||
# choice = input("Type in the number to choose a category and type enter to confirm\n")
|
||||
|
||||
choice = '2'
|
||||
if choice == '1':
|
||||
img_input = cv.imread("beach.jpg")
|
||||
print("You choose: %s - beach\n" % choice)
|
||||
if choice == '2':
|
||||
img_input = cv.imread("building.jpg")
|
||||
print("You choose: %s - building\n" % choice)
|
||||
if choice == '3':
|
||||
img_input = cv.imread("bus.jpg")
|
||||
print("You choose: %s - bus\n" % choice)
|
||||
if choice == '4':
|
||||
img_input = cv.imread("dinosaur.jpg")
|
||||
print("You choose: %s - dinosaur\n" % choice)
|
||||
if choice == '5':
|
||||
img_input = cv.imread("flower.jpg")
|
||||
print("You choose: %s - flower\n" % choice)
|
||||
if choice == '6':
|
||||
img_input = cv.imread("horse.jpg")
|
||||
print("You choose: %s - horse\n" % choice)
|
||||
if choice == '7':
|
||||
img_input = cv.imread("man.jpg")
|
||||
print("You choose: %s - man\n" % choice)
|
||||
|
||||
min_diff = 1e50
|
||||
|
||||
# src_input = cv.imread("man.jpg")
|
||||
cv.imshow("Input", img_input)
|
||||
|
||||
# change the image to gray scale
|
||||
src_gray = cv.cvtColor(img_input, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# read image database
|
||||
database = sorted(glob(database_dir + "/*.jpg"))
|
||||
|
||||
print('working')
|
||||
diff_array = []
|
||||
for img in database:
|
||||
# read image
|
||||
img_rgb = cv.imread(img)
|
||||
|
||||
# compare the two images
|
||||
diff = compareImgs(img_input, img_rgb)
|
||||
|
||||
# compare the two images by histogram, uncomment the following line to use histogram
|
||||
# diff = compareImgs_hist(src_gray, img_gray)
|
||||
# print(img, diff)
|
||||
diff_array.append([img,diff, img_rgb])
|
||||
|
||||
diff_array.sort(key=lambda x: x[1])
|
||||
result = diff_array[0]
|
||||
min_diff = result[1]
|
||||
closest_img = result[2]
|
||||
|
||||
i = 0
|
||||
for diff in diff_array:
|
||||
i += 1
|
||||
# SIFT_debug(img_input, diff[2])
|
||||
filename = diff[0].replace('image.orig/','')
|
||||
category = filename[0]
|
||||
|
||||
if (category=="2"):
|
||||
pprint('found at ' + str(i))
|
||||
matches = SIFT_compare(img_input, diff[2])
|
||||
print(diff[0],matches)
|
||||
result = diff
|
||||
min_diff = result[1]
|
||||
closest_img = result[2]
|
||||
# SIFT_debug(img_input, closest_img)
|
||||
break
|
||||
|
||||
# print("the most similar image is %s, the pixel-by-pixel difference is %f " % (result, min_diff))
|
||||
# print("\n")
|
||||
|
||||
cv.imshow("Result", closest_img)
|
||||
cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
|
||||
def SIFT():
|
||||
img1 = cv.imread("flower.jpg")
|
||||
img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print('Error loading images!')
|
||||
exit(0)
|
||||
#-- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
#-- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
#-- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
#-- Show detected matches
|
||||
cv.imshow('Matches: SIFT (Python)', img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key = lambda x:x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x:x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
#-- Show detected matches
|
||||
cv.imshow('Good Matches: SIFT (Python)', img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
|
||||
def SIFT_debug(img1, img2):
|
||||
# img1 = cv.imread("flower.jpg")
|
||||
# img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print('Error loading images!')
|
||||
exit(0)
|
||||
#-- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
#-- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
#-- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
#-- Show detected matches
|
||||
cv.imshow('Matches: SIFT (Python)', img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key = lambda x:x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x:x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
#-- Show detected matches
|
||||
cv.imshow('Good Matches: SIFT (Python)', img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
def SIFT_compare(img1, img2):
|
||||
# img1 = cv.imread("flower.jpg")
|
||||
# img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print('Error loading images!')
|
||||
exit(0)
|
||||
#-- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
#-- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
|
||||
#-- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
|
||||
# cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
|
||||
#-- Show detected matches
|
||||
# cv.imshow('Matches: SIFT (Python)', img_matches)
|
||||
# cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key = lambda x:x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x:x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
|
||||
|
||||
# cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
#-- Show detected matches
|
||||
# cv.imshow('Good Matches: SIFT (Python)', img_matches)
|
||||
# cv.waitKey()
|
||||
return len(good_matches)
|
||||
|
||||
def main():
|
||||
# img = cv.imread("beach.jpg")
|
||||
# cv.imshow("Image", img)
|
||||
# from matplotlib import pyplot as plt
|
||||
# plt.hist(img.ravel(),10,[0,256]); plt.show()
|
||||
# gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
||||
# cv.imshow("Gray Image", gray_img)
|
||||
# cv.waitKey()
|
||||
retrieval()
|
||||
|
||||
print("done")
|
||||
|
||||
import os,sys
|
||||
sys.exit()
|
||||
|
||||
print("1: Image retrieval demo")
|
||||
print("2: SIFT demo")
|
||||
number = int(input("Type in the number to choose a demo and type enter to confirm\n"))
|
||||
|
||||
if number == 1:
|
||||
retrieval()
|
||||
elif number == 2:
|
||||
SIFT()
|
||||
# pass
|
||||
else:
|
||||
print("Invalid input")
|
||||
exit()
|
||||
|
||||
main()
|
388
vinniesniper-54816/task1/_ref/2022-Codes-Python/demo_draft2.py
Normal file
388
vinniesniper-54816/task1/_ref/2022-Codes-Python/demo_draft2.py
Normal file
@@ -0,0 +1,388 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
from glob import glob
|
||||
import os, sys
|
||||
from pprint import pprint
|
||||
|
||||
# the directory of the image database
|
||||
database_dir = "image.orig"
|
||||
|
||||
|
||||
# Compute pixel-by-pixel difference and return the sum
|
||||
def compareImgs(img1, img2):
|
||||
# resize img2 to img1
|
||||
img2 = cv.resize(img2, (img1.shape[1], img1.shape[0]))
|
||||
diff = cv.absdiff(img1, img2)
|
||||
return diff.sum()
|
||||
|
||||
|
||||
def compareImgs_hist(img1, img2):
|
||||
width, height = img1.shape[1], img1.shape[0]
|
||||
img2 = cv.resize(img2, (width, height))
|
||||
num_bins = 10
|
||||
hist1 = [0] * num_bins
|
||||
hist2 = [0] * num_bins
|
||||
bin_width = 255.0 / num_bins + 1e-4
|
||||
# compute histogram from scratch
|
||||
|
||||
# for w in range(width):
|
||||
# for h in range(height):
|
||||
# hist1[int(img1[h, w] / bin_width)] += 1
|
||||
# hist2[int(img2[h, w] / bin_width)] += 1
|
||||
|
||||
# compute histogram by using opencv function
|
||||
# https://docs.opencv.org/4.x/d6/dc7/group__imgproc__hist.html#ga4b2b5fd75503ff9e6844cc4dcdaed35d
|
||||
|
||||
hist1 = cv.calcHist([img1], [0], None, [num_bins], [0, 255])
|
||||
hist2 = cv.calcHist([img2], [0], None, [num_bins], [0, 255])
|
||||
sum = 0
|
||||
for i in range(num_bins):
|
||||
sum += abs(hist1[i] - hist2[i])
|
||||
return sum / float(width * height)
|
||||
|
||||
|
||||
def color_layout_descriptor(image, num_blocks=8, resize_to_px=256):
|
||||
resized_image = cv.resize(image, (resize_to_px, resize_to_px))
|
||||
ycrcb_image = cv.cvtColor(resized_image, cv.COLOR_BGR2YCrCb)
|
||||
|
||||
# Step 5: Divide the image into sub-blocks
|
||||
block_size = int(256 / num_blocks)
|
||||
blocks = []
|
||||
for i in range(num_blocks):
|
||||
for j in range(num_blocks):
|
||||
block = ycrcb_image[
|
||||
i * block_size : (i + 1) * block_size,
|
||||
j * block_size : (j + 1) * block_size,
|
||||
]
|
||||
blocks.append(block)
|
||||
|
||||
# Step 6: Extract features from each sub-block
|
||||
i = 0
|
||||
features = []
|
||||
center_features = []
|
||||
for block in blocks:
|
||||
# Compute the mean and standard deviation of each color channel
|
||||
mean_y, mean_cr, mean_cb = np.mean(block, axis=(0, 1))
|
||||
std_y, std_cr, std_cb = np.std(block, axis=(0, 1))
|
||||
features.extend([mean_y, mean_cr, mean_cb, std_y, std_cr, std_cb])
|
||||
|
||||
if (i == 28) or (i == 29) or (i == 36) or (i == 37):
|
||||
center_features.extend([mean_y, mean_cr, mean_cb, std_y, std_cr, std_cb])
|
||||
i += 1
|
||||
|
||||
# Step 7: Concatenate features into a single vector
|
||||
cld_full_picture = np.array(features)
|
||||
cld_center = np.array(center_features)
|
||||
|
||||
return (cld_full_picture, cld_center)
|
||||
|
||||
|
||||
def colorlayoutCompare(cld1, cld2):
|
||||
distance = np.linalg.norm(cld1 - cld2)
|
||||
|
||||
similarity = 1.0 / (1.0 + distance)
|
||||
|
||||
return (distance, similarity)
|
||||
|
||||
|
||||
def retrieval(choice="3"):
|
||||
print("testing retrieval ...")
|
||||
# print("1: beach")
|
||||
# print("2: building")
|
||||
# print("3: bus")
|
||||
# print("4: dinosaur")
|
||||
# print("5: flower")
|
||||
# print("6: horse")
|
||||
# print("7: man")
|
||||
|
||||
# choice = input("Type in the number to choose a category and type enter to confirm\n")
|
||||
|
||||
if choice == "1":
|
||||
img_input = cv.imread("beach.jpg")
|
||||
print("test: %s - beach" % choice)
|
||||
if choice == "2":
|
||||
img_input = cv.imread("building.jpg")
|
||||
print("test: %s - building" % choice)
|
||||
if choice == "3":
|
||||
img_input = cv.imread("bus.jpg")
|
||||
print("test: %s - bus" % choice)
|
||||
if choice == "4":
|
||||
img_input = cv.imread("dinosaur.jpg")
|
||||
print("test: %s - dinosaur" % choice)
|
||||
if choice == "5":
|
||||
img_input = cv.imread("flower.jpg")
|
||||
print("test: %s - flower" % choice)
|
||||
if choice == "6":
|
||||
img_input = cv.imread("horse.jpg")
|
||||
print("test: %s - horse" % choice)
|
||||
if choice == "7":
|
||||
img_input = cv.imread("man.jpg")
|
||||
print("test: %s - man" % choice)
|
||||
|
||||
min_diff = 1e50
|
||||
# src_input = cv.imread("man.jpg")
|
||||
# cv.imshow("Input", img_input)
|
||||
# change the image to gray scale
|
||||
# src_gray = cv.cvtColor(img_input, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# read image database
|
||||
database = sorted(glob(database_dir + "/*.jpg"))
|
||||
|
||||
descriptors = []
|
||||
|
||||
(cld1, cld1_center) = color_layout_descriptor(img_input)
|
||||
for img in database:
|
||||
print(f"processing {img}", end="\r")
|
||||
|
||||
# read image
|
||||
img_rgb = cv.imread(img)
|
||||
(cld2, cld2_center) = color_layout_descriptor(img_rgb)
|
||||
|
||||
# compare the two images
|
||||
# diff = compareImgs(img_input, img_rgb)
|
||||
(diff_full, s_full) = colorlayoutCompare(cld1, cld2)
|
||||
(diff_center, s_center) = colorlayoutCompare(cld1_center, cld2_center)
|
||||
|
||||
# compare the two images by histogram, uncomment the following line to use histogram
|
||||
# diff = compareImgs_hist(src_gray, img_gray)
|
||||
# print(img, diff)
|
||||
|
||||
len_good_matches = SIFT_compare(img_input, img_rgb)
|
||||
|
||||
descriptors.append([img, img_rgb, s_full, s_center, len_good_matches])
|
||||
print("\nprocess done")
|
||||
|
||||
normalized_descriptors = []
|
||||
max_s_full = max(descriptors, key=lambda x: x[2])[2]
|
||||
min_s_full = min(descriptors, key=lambda x: x[2])[2]
|
||||
|
||||
max_s_center = max(descriptors, key=lambda x: x[3])[3]
|
||||
min_s_center = min(descriptors, key=lambda x: x[3])[3]
|
||||
|
||||
max_good_matches = max(descriptors, key=lambda x: x[4])[4]
|
||||
min_good_matches = min(descriptors, key=lambda x: x[4])[4]
|
||||
|
||||
for descriptor in descriptors:
|
||||
normalized_s_full = (descriptor[2] - min_s_full) / (max_s_full - min_s_full)
|
||||
normalized_s_center = (descriptor[3] - min_s_center) / (max_s_center - min_s_center)
|
||||
normalized_good_matches = (descriptor[4] - min_good_matches) / (max_good_matches - min_good_matches)
|
||||
|
||||
normalized_descriptors.append([descriptor[0], descriptor[1], normalized_s_full, normalized_s_center, normalized_good_matches])
|
||||
|
||||
print("\nnormalized descriptors done")
|
||||
|
||||
for descriptor in normalized_descriptors:
|
||||
print(descriptor[0], descriptor[2], descriptor[3], descriptor[4])
|
||||
|
||||
import csv
|
||||
|
||||
with open("descriptor.csv", "w", newline="") as csvfile:
|
||||
spamwriter = csv.writer(csvfile)
|
||||
spamwriter.writerow(["image", "similarity_full", "similarity_center", "good_matches"])
|
||||
for descriptor in normalized_descriptors:
|
||||
spamwriter.writerow([descriptor[0], descriptor[2], descriptor[3], descriptor[4]])
|
||||
|
||||
import xlsxwriter
|
||||
|
||||
workbook = xlsxwriter.Workbook("descriptor.xlsx")
|
||||
worksheet = workbook.add_worksheet()
|
||||
row = 0
|
||||
worksheet.write(row, 0, "image")
|
||||
worksheet.write(row, 1, "similarity_full")
|
||||
worksheet.write(row, 2, "similarity_center")
|
||||
worksheet.write(row, 3, "good_matches")
|
||||
row += 1
|
||||
for descriptor in normalized_descriptors:
|
||||
worksheet.write(row, 0, descriptor[0])
|
||||
worksheet.write(row, 1, descriptor[2])
|
||||
worksheet.write(row, 2, descriptor[3])
|
||||
worksheet.write(row, 3, descriptor[4])
|
||||
row += 1
|
||||
workbook.close()
|
||||
|
||||
sys.exit()
|
||||
|
||||
# sort by s_full, largest first
|
||||
descriptors.sort(key=lambda x: x[2])
|
||||
result = descriptors[0]
|
||||
closest_img = result[1]
|
||||
|
||||
# get feature match
|
||||
diff_with_matches = []
|
||||
for descriptor in descriptors[0:5]:
|
||||
# SIFT_debug(img_input, diff[2])
|
||||
full_file_name = descriptor[0]
|
||||
img = descriptor[1]
|
||||
diff_full = descriptor[2]
|
||||
diff_center = descriptor[3]
|
||||
|
||||
filename_only = full_file_name.replace("image.orig/", "")
|
||||
category = filename_only[0]
|
||||
len_good_matches = SIFT_compare(img_input, img)
|
||||
|
||||
diff_with_matches.append([full_file_name, img, len_good_matches, 0, s_full, s_center])
|
||||
|
||||
matches = sorted(diff_with_matches, key=lambda x: x[4], reverse=True)
|
||||
for match in matches:
|
||||
pprint((match[0], match[2], match[4], match[5]))
|
||||
|
||||
[full_file_name, closest_img, len_good_matches, _, s_full, s_center] = matches[0]
|
||||
|
||||
# print("the most similar image is %s, the pixel-by-pixel difference is %f " % (result, min_diff))
|
||||
# print("\n")
|
||||
|
||||
cv.imshow("Result", closest_img)
|
||||
# cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
|
||||
filename_only = full_file_name.replace("image.orig/", "")
|
||||
category = filename_only[0]
|
||||
|
||||
print("f:" + filename_only + ": c:" + category)
|
||||
|
||||
return category
|
||||
|
||||
|
||||
def SIFT():
|
||||
img1 = cv.imread("flower.jpg")
|
||||
img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
# -- Show detected matches
|
||||
cv.imshow("Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
cv.imshow("Good Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
|
||||
def SIFT_debug(img1, img2):
|
||||
# img1 = cv.imread("flower.jpg")
|
||||
# img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
# -- Show detected matches
|
||||
cv.imshow("Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
cv.imshow("Good Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
|
||||
def SIFT_compare(img1, img2):
|
||||
# img1 = cv.imread("flower.jpg")
|
||||
# img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
# cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
|
||||
# -- Show detected matches
|
||||
# cv.imshow('Matches: SIFT (Python)', img_matches)
|
||||
# cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
|
||||
# cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
# cv.imshow('Good Matches: SIFT (Python)', img_matches)
|
||||
# cv.waitKey()
|
||||
return len(good_matches)
|
||||
|
||||
|
||||
def test():
|
||||
test_result = True
|
||||
# 1, 2, 4, 7
|
||||
for i in [6]:
|
||||
if str(i) == retrieval(str(i)):
|
||||
print("test ok")
|
||||
else:
|
||||
test_result = False
|
||||
|
||||
if test_result:
|
||||
print("all test ok")
|
||||
pass
|
||||
else:
|
||||
print("some test failed")
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
test()
|
||||
sys.exit()
|
||||
|
||||
print("1: Image retrieval demo")
|
||||
print("2: SIFT demo")
|
||||
number = int(input("Type in the number to choose a demo and type enter to confirm\n"))
|
||||
|
||||
if number == 1:
|
||||
retrieval()
|
||||
elif number == 2:
|
||||
SIFT()
|
||||
# pass
|
||||
else:
|
||||
print("Invalid input")
|
||||
exit()
|
||||
|
||||
|
||||
main()
|
@@ -0,0 +1,316 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
from glob import glob
|
||||
import os, sys
|
||||
from pprint import pprint
|
||||
|
||||
# the directory of the image database
|
||||
database_dir = "image.orig"
|
||||
|
||||
|
||||
# Compute pixel-by-pixel difference and return the sum
|
||||
def compareImgs(img1, img2):
|
||||
# resize img2 to img1
|
||||
img2 = cv.resize(img2, (img1.shape[1], img1.shape[0]))
|
||||
diff = cv.absdiff(img1, img2)
|
||||
return diff.sum()
|
||||
|
||||
|
||||
def compareImgs_hist(img1, img2):
|
||||
width, height = img1.shape[1], img1.shape[0]
|
||||
img2 = cv.resize(img2, (width, height))
|
||||
num_bins = 10
|
||||
hist1 = [0] * num_bins
|
||||
hist2 = [0] * num_bins
|
||||
bin_width = 255.0 / num_bins + 1e-4
|
||||
# compute histogram from scratch
|
||||
|
||||
# for w in range(width):
|
||||
# for h in range(height):
|
||||
# hist1[int(img1[h, w] / bin_width)] += 1
|
||||
# hist2[int(img2[h, w] / bin_width)] += 1
|
||||
|
||||
# compute histogram by using opencv function
|
||||
# https://docs.opencv.org/4.x/d6/dc7/group__imgproc__hist.html#ga4b2b5fd75503ff9e6844cc4dcdaed35d
|
||||
|
||||
hist1 = cv.calcHist([img1], [0], None, [num_bins], [0, 255])
|
||||
hist2 = cv.calcHist([img2], [0], None, [num_bins], [0, 255])
|
||||
sum = 0
|
||||
for i in range(num_bins):
|
||||
sum += abs(hist1[i] - hist2[i])
|
||||
return sum / float(width * height)
|
||||
|
||||
|
||||
def color_layout_descriptor(image, num_blocks=8, resize_to_px=256):
|
||||
resized_image = cv.resize(image, (resize_to_px, resize_to_px))
|
||||
ycrcb_image = cv.cvtColor(resized_image, cv.COLOR_BGR2YCrCb)
|
||||
|
||||
# Step 5: Divide the image into sub-blocks
|
||||
block_size = int(resize_to_px / num_blocks)
|
||||
blocks = []
|
||||
for i in range(num_blocks):
|
||||
for j in range(num_blocks):
|
||||
block = ycrcb_image[
|
||||
i * block_size : (i + 1) * block_size,
|
||||
j * block_size : (j + 1) * block_size,
|
||||
]
|
||||
blocks.append(block)
|
||||
|
||||
# Step 6: Extract features from each sub-block
|
||||
features = []
|
||||
for block in blocks:
|
||||
# Compute the mean and standard deviation of each color channel
|
||||
mean_y, mean_cr, mean_cb = np.mean(block, axis=(0, 1))
|
||||
std_y, std_cr, std_cb = np.std(block, axis=(0, 1))
|
||||
features.extend([mean_y, mean_cr, mean_cb, std_y, std_cr, std_cb])
|
||||
|
||||
# Step 7: Concatenate features into a single vector
|
||||
cld_vector = np.array(features)
|
||||
|
||||
return cld_vector
|
||||
|
||||
|
||||
def colorlayoutCompare(img1, img2):
|
||||
cld1 = color_layout_descriptor(img1)
|
||||
cld2 = color_layout_descriptor(img2)
|
||||
distance = np.linalg.norm(cld1 - cld2)
|
||||
|
||||
similarity = 1.0 / (1.0 + distance)
|
||||
|
||||
return (distance, similarity)
|
||||
|
||||
|
||||
def retrieval(choice="3"):
|
||||
print("testing retrieval ...")
|
||||
# print("1: beach")
|
||||
# print("2: building")
|
||||
# print("3: bus")
|
||||
# print("4: dinosaur")
|
||||
# print("5: flower")
|
||||
# print("6: horse")
|
||||
# print("7: man")
|
||||
|
||||
# choice = input("Type in the number to choose a category and type enter to confirm\n")
|
||||
|
||||
if choice == "1":
|
||||
img_input = cv.imread("beach.jpg")
|
||||
print("You choose: %s - beach\n" % choice)
|
||||
if choice == "2":
|
||||
img_input = cv.imread("building.jpg")
|
||||
print("You choose: %s - building\n" % choice)
|
||||
if choice == "3":
|
||||
img_input = cv.imread("bus.jpg")
|
||||
print("You choose: %s - bus\n" % choice)
|
||||
if choice == "4":
|
||||
img_input = cv.imread("dinosaur.jpg")
|
||||
print("You choose: %s - dinosaur\n" % choice)
|
||||
if choice == "5":
|
||||
img_input = cv.imread("flower.jpg")
|
||||
print("You choose: %s - flower\n" % choice)
|
||||
if choice == "6":
|
||||
img_input = cv.imread("horse.jpg")
|
||||
print("You choose: %s - horse\n" % choice)
|
||||
if choice == "7":
|
||||
img_input = cv.imread("man.jpg")
|
||||
print("You choose: %s - man\n" % choice)
|
||||
|
||||
min_diff = 1e50
|
||||
|
||||
# src_input = cv.imread("man.jpg")
|
||||
# cv.imshow("Input", img_input)
|
||||
|
||||
# change the image to gray scale
|
||||
src_gray = cv.cvtColor(img_input, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# read image database
|
||||
database = sorted(glob(database_dir + "/*.jpg"))
|
||||
|
||||
diff_array = []
|
||||
for img in database:
|
||||
print(f"processing {img}", end="\r")
|
||||
|
||||
# read image
|
||||
img_rgb = cv.imread(img)
|
||||
|
||||
# compare the two images
|
||||
# diff = compareImgs(img_input, img_rgb)
|
||||
(d, s) = colorlayoutCompare(img_input, img_rgb)
|
||||
diff = d
|
||||
|
||||
# compare the two images by histogram, uncomment the following line to use histogram
|
||||
# diff = compareImgs_hist(src_gray, img_gray)
|
||||
# print(img, diff)
|
||||
diff_array.append([img, diff, img_rgb])
|
||||
|
||||
diff_array.sort(key=lambda x: x[1])
|
||||
result = diff_array[0]
|
||||
min_diff = result[1]
|
||||
closest_img = result[2]
|
||||
|
||||
# get feature match
|
||||
diff_with_matches = []
|
||||
i = 0
|
||||
for diff in diff_array[0:20]:
|
||||
i += 1
|
||||
# SIFT_debug(img_input, diff[2])
|
||||
full_file_name = diff[0]
|
||||
img = diff[2]
|
||||
|
||||
filename_only = full_file_name.replace("image.orig/", "")
|
||||
category = filename_only[0]
|
||||
len_good_matches = SIFT_compare(img_input, img)
|
||||
|
||||
diff_with_matches.append([full_file_name, len_good_matches, d, img])
|
||||
|
||||
matches = sorted(diff_with_matches, key=lambda x: x[1], reverse=True)
|
||||
|
||||
[full_file_name, len_good_matches, d, closest_img] = matches[0]
|
||||
|
||||
pprint(full_file_name)
|
||||
|
||||
# print("the most similar image is %s, the pixel-by-pixel difference is %f " % (result, min_diff))
|
||||
# print("\n")
|
||||
|
||||
cv.imshow("Result", closest_img)
|
||||
# cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
|
||||
print("cat:" + category + ": found")
|
||||
|
||||
return category
|
||||
|
||||
|
||||
def SIFT():
|
||||
img1 = cv.imread("flower.jpg")
|
||||
img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
# -- Show detected matches
|
||||
cv.imshow("Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
cv.imshow("Good Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
|
||||
def SIFT_debug(img1, img2):
|
||||
# img1 = cv.imread("flower.jpg")
|
||||
# img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
# -- Show detected matches
|
||||
cv.imshow("Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
cv.imshow("Good Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
|
||||
def SIFT_compare(img1, img2):
|
||||
# img1 = cv.imread("flower.jpg")
|
||||
# img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
# cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
|
||||
# -- Show detected matches
|
||||
# cv.imshow('Matches: SIFT (Python)', img_matches)
|
||||
# cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
|
||||
# cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
# cv.imshow('Good Matches: SIFT (Python)', img_matches)
|
||||
# cv.waitKey()
|
||||
return len(good_matches)
|
||||
|
||||
|
||||
def main():
|
||||
print("cat 1 test passed" if "1" == retrieval("1") else "cat 1 test failed") # OK
|
||||
# retrieval("2") # OK
|
||||
# retrieval("4") # OK
|
||||
# retrieval("6") # OK
|
||||
# retrieval("7") # OK
|
||||
print(retrieval("3")) # failed
|
||||
# retrieval("5") # failed
|
||||
|
||||
print("done")
|
||||
|
||||
sys.exit()
|
||||
|
||||
print("1: Image retrieval demo")
|
||||
print("2: SIFT demo")
|
||||
number = int(input("Type in the number to choose a demo and type enter to confirm\n"))
|
||||
|
||||
if number == 1:
|
||||
retrieval()
|
||||
elif number == 2:
|
||||
SIFT()
|
||||
# pass
|
||||
else:
|
||||
print("Invalid input")
|
||||
exit()
|
||||
|
||||
|
||||
main()
|
@@ -0,0 +1,355 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
from glob import glob
|
||||
import os, sys
|
||||
from pprint import pprint
|
||||
|
||||
# the directory of the image database
|
||||
database_dir = "image.orig"
|
||||
|
||||
|
||||
# Compute pixel-by-pixel difference and return the sum
|
||||
def compareImgs(img1, img2):
|
||||
# resize img2 to img1
|
||||
img2 = cv.resize(img2, (img1.shape[1], img1.shape[0]))
|
||||
diff = cv.absdiff(img1, img2)
|
||||
return diff.sum()
|
||||
|
||||
|
||||
def compareImgs_hist(img1, img2):
|
||||
width, height = img1.shape[1], img1.shape[0]
|
||||
img2 = cv.resize(img2, (width, height))
|
||||
num_bins = 10
|
||||
hist1 = [0] * num_bins
|
||||
hist2 = [0] * num_bins
|
||||
bin_width = 255.0 / num_bins + 1e-4
|
||||
# compute histogram from scratch
|
||||
|
||||
# for w in range(width):
|
||||
# for h in range(height):
|
||||
# hist1[int(img1[h, w] / bin_width)] += 1
|
||||
# hist2[int(img2[h, w] / bin_width)] += 1
|
||||
|
||||
# compute histogram by using opencv function
|
||||
# https://docs.opencv.org/4.x/d6/dc7/group__imgproc__hist.html#ga4b2b5fd75503ff9e6844cc4dcdaed35d
|
||||
|
||||
hist1 = cv.calcHist([img1], [0], None, [num_bins], [0, 255])
|
||||
hist2 = cv.calcHist([img2], [0], None, [num_bins], [0, 255])
|
||||
sum = 0
|
||||
for i in range(num_bins):
|
||||
sum += abs(hist1[i] - hist2[i])
|
||||
return sum / float(width * height)
|
||||
|
||||
|
||||
def color_layout_descriptor(image, num_blocks=8, resize_to_px=256):
|
||||
resized_image = cv.resize(image, (resize_to_px, resize_to_px))
|
||||
ycrcb_image = cv.cvtColor(resized_image, cv.COLOR_BGR2YCrCb)
|
||||
|
||||
# Step 5: Divide the image into sub-blocks
|
||||
block_size = int(256 / num_blocks)
|
||||
blocks = []
|
||||
for i in range(num_blocks):
|
||||
for j in range(num_blocks):
|
||||
block = ycrcb_image[
|
||||
i * block_size : (i + 1) * block_size,
|
||||
j * block_size : (j + 1) * block_size,
|
||||
]
|
||||
blocks.append(block)
|
||||
|
||||
# Step 6: Extract features from each sub-block
|
||||
i = 0
|
||||
features = []
|
||||
center_features = []
|
||||
for block in blocks:
|
||||
# Compute the mean and standard deviation of each color channel
|
||||
mean_y, mean_cr, mean_cb = np.mean(block, axis=(0, 1))
|
||||
std_y, std_cr, std_cb = np.std(block, axis=(0, 1))
|
||||
features.extend([mean_y, mean_cr, mean_cb, std_y, std_cr, std_cb])
|
||||
|
||||
if (i == 28) or (i == 29) or (i == 36) or (i == 37):
|
||||
center_features.extend([mean_y, mean_cr, mean_cb, std_y, std_cr, std_cb])
|
||||
i += 1
|
||||
|
||||
# Step 7: Concatenate features into a single vector
|
||||
cld_full_picture = np.array(features)
|
||||
cld_center = np.array(center_features)
|
||||
|
||||
return (cld_full_picture, cld_center)
|
||||
|
||||
|
||||
def colorlayoutCompare(cld1, cld2):
|
||||
distance = np.linalg.norm(cld1 - cld2)
|
||||
|
||||
similarity = 1.0 / (1.0 + distance)
|
||||
|
||||
return (distance, similarity)
|
||||
|
||||
|
||||
def retrieval(choice="3"):
|
||||
print("testing retrieval ...")
|
||||
# print("1: beach")
|
||||
# print("2: building")
|
||||
# print("3: bus")
|
||||
# print("4: dinosaur")
|
||||
# print("5: flower")
|
||||
# print("6: horse")
|
||||
# print("7: man")
|
||||
|
||||
# choice = input("Type in the number to choose a category and type enter to confirm\n")
|
||||
|
||||
if choice == "1":
|
||||
img_input = cv.imread("beach.jpg")
|
||||
print("test: %s - beach" % choice)
|
||||
if choice == "2":
|
||||
img_input = cv.imread("building.jpg")
|
||||
print("test: %s - building" % choice)
|
||||
if choice == "3":
|
||||
img_input = cv.imread("bus.jpg")
|
||||
print("test: %s - bus" % choice)
|
||||
if choice == "4":
|
||||
img_input = cv.imread("dinosaur.jpg")
|
||||
print("test: %s - dinosaur" % choice)
|
||||
if choice == "5":
|
||||
img_input = cv.imread("flower.jpg")
|
||||
print("test: %s - flower" % choice)
|
||||
if choice == "6":
|
||||
img_input = cv.imread("horse.jpg")
|
||||
print("test: %s - horse" % choice)
|
||||
if choice == "7":
|
||||
img_input = cv.imread("man.jpg")
|
||||
print("test: %s - man" % choice)
|
||||
|
||||
min_diff = 1e50
|
||||
# src_input = cv.imread("man.jpg")
|
||||
# cv.imshow("Input", img_input)
|
||||
# change the image to gray scale
|
||||
# src_gray = cv.cvtColor(img_input, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# read image database
|
||||
database = sorted(glob(database_dir + "/*.jpg"))
|
||||
|
||||
descriptors = []
|
||||
|
||||
(cld1, cld1_center) = color_layout_descriptor(img_input)
|
||||
for img in database:
|
||||
print(f"processing {img}", end="\r")
|
||||
|
||||
# read image
|
||||
img_rgb = cv.imread(img)
|
||||
(cld2, cld2_center) = color_layout_descriptor(img_rgb)
|
||||
|
||||
# compare the two images
|
||||
# diff = compareImgs(img_input, img_rgb)
|
||||
(diff_full, s_full) = colorlayoutCompare(cld1, cld2)
|
||||
(diff_center, s_center) = colorlayoutCompare(cld1_center, cld2_center)
|
||||
|
||||
# compare the two images by histogram, uncomment the following line to use histogram
|
||||
# diff = compareImgs_hist(src_gray, img_gray)
|
||||
# print(img, diff)
|
||||
|
||||
len_good_matches = SIFT_compare(img_input, img_rgb)
|
||||
|
||||
descriptors.append([img, img_rgb, s_full, s_center, len_good_matches])
|
||||
print("\nprocess done")
|
||||
|
||||
normalized_descriptors = []
|
||||
max_s_full = max(descriptors, key=lambda x: x[2])[2]
|
||||
min_s_full = min(descriptors, key=lambda x: x[2])[2]
|
||||
|
||||
max_s_center = max(descriptors, key=lambda x: x[3])[3]
|
||||
min_s_center = min(descriptors, key=lambda x: x[3])[3]
|
||||
|
||||
max_good_matches = max(descriptors, key=lambda x: x[4])[4]
|
||||
min_good_matches = min(descriptors, key=lambda x: x[4])[4]
|
||||
|
||||
for descriptor in descriptors:
|
||||
normalized_s_full = (descriptor[2] - min_s_full) / (max_s_full - min_s_full)
|
||||
normalized_s_center = (descriptor[3] - min_s_center) / (max_s_center - min_s_center)
|
||||
normalized_good_matches = (descriptor[4] - min_good_matches) / (max_good_matches - min_good_matches)
|
||||
|
||||
normalized_descriptors.append([descriptor[0], descriptor[1], normalized_s_full, normalized_s_center, normalized_good_matches])
|
||||
|
||||
print("\nnormalized descriptors done")
|
||||
|
||||
# sort by s_full, largest first
|
||||
normalized_descriptors.sort(key=lambda x: x[2])
|
||||
result = normalized_descriptors[0]
|
||||
closest_img = result[1]
|
||||
|
||||
# get feature match
|
||||
diff_with_matches = []
|
||||
for descriptor in normalized_descriptors[0:5]:
|
||||
# SIFT_debug(img_input, diff[2])
|
||||
full_file_name = descriptor[0]
|
||||
img = descriptor[1]
|
||||
|
||||
filename_only = full_file_name.replace("image.orig/", "")
|
||||
category = filename_only[0]
|
||||
len_good_matches = SIFT_compare(img_input, img)
|
||||
|
||||
diff_with_matches.append([full_file_name, img, len_good_matches, 0, s_full, s_center])
|
||||
|
||||
matches = sorted(diff_with_matches, key=lambda x: x[4], reverse=True)
|
||||
for match in matches:
|
||||
pprint((match[0], match[2], match[4], match[5]))
|
||||
|
||||
[full_file_name, closest_img, len_good_matches, _, s_full, s_center] = matches[0]
|
||||
|
||||
# print("the most similar image is %s, the pixel-by-pixel difference is %f " % (result, min_diff))
|
||||
# print("\n")
|
||||
|
||||
cv.imshow("Result", closest_img)
|
||||
# cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
|
||||
filename_only = full_file_name.replace("image.orig/", "")
|
||||
category = filename_only[0]
|
||||
|
||||
print("f:" + filename_only + ": c:" + category)
|
||||
|
||||
return category
|
||||
|
||||
|
||||
def SIFT():
|
||||
img1 = cv.imread("flower.jpg")
|
||||
img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
# -- Show detected matches
|
||||
cv.imshow("Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
cv.imshow("Good Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
|
||||
def SIFT_debug(img1, img2):
|
||||
# img1 = cv.imread("flower.jpg")
|
||||
# img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
# -- Show detected matches
|
||||
cv.imshow("Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
cv.imshow("Good Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
|
||||
def SIFT_compare(img1, img2):
|
||||
# img1 = cv.imread("flower.jpg")
|
||||
# img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
# cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
|
||||
# -- Show detected matches
|
||||
# cv.imshow('Matches: SIFT (Python)', img_matches)
|
||||
# cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
|
||||
# cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
# cv.imshow('Good Matches: SIFT (Python)', img_matches)
|
||||
# cv.waitKey()
|
||||
return len(good_matches)
|
||||
|
||||
|
||||
def test():
|
||||
test_result = True
|
||||
# 1, 2, 4, 7
|
||||
for i in [1]:
|
||||
if str(i) == retrieval(str(i)):
|
||||
print("test ok")
|
||||
else:
|
||||
test_result = False
|
||||
|
||||
if test_result:
|
||||
print("all test ok")
|
||||
pass
|
||||
else:
|
||||
print("some test failed")
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
test()
|
||||
sys.exit()
|
||||
|
||||
print("1: Image retrieval demo")
|
||||
print("2: SIFT demo")
|
||||
number = int(input("Type in the number to choose a demo and type enter to confirm\n"))
|
||||
|
||||
if number == 1:
|
||||
retrieval()
|
||||
elif number == 2:
|
||||
SIFT()
|
||||
# pass
|
||||
else:
|
||||
print("Invalid input")
|
||||
exit()
|
||||
|
||||
|
||||
main()
|
@@ -0,0 +1,328 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
from glob import glob
|
||||
import os, sys
|
||||
from pprint import pprint
|
||||
|
||||
# the directory of the image database
|
||||
database_dir = "image.orig"
|
||||
|
||||
|
||||
# Compute pixel-by-pixel difference and return the sum
|
||||
def compareImgs(img1, img2):
|
||||
# resize img2 to img1
|
||||
img2 = cv.resize(img2, (img1.shape[1], img1.shape[0]))
|
||||
diff = cv.absdiff(img1, img2)
|
||||
return diff.sum()
|
||||
|
||||
|
||||
def compareImgs_hist(img1, img2):
|
||||
width, height = img1.shape[1], img1.shape[0]
|
||||
img2 = cv.resize(img2, (width, height))
|
||||
num_bins = 10
|
||||
hist1 = [0] * num_bins
|
||||
hist2 = [0] * num_bins
|
||||
bin_width = 255.0 / num_bins + 1e-4
|
||||
# compute histogram from scratch
|
||||
|
||||
# for w in range(width):
|
||||
# for h in range(height):
|
||||
# hist1[int(img1[h, w] / bin_width)] += 1
|
||||
# hist2[int(img2[h, w] / bin_width)] += 1
|
||||
|
||||
# compute histogram by using opencv function
|
||||
# https://docs.opencv.org/4.x/d6/dc7/group__imgproc__hist.html#ga4b2b5fd75503ff9e6844cc4dcdaed35d
|
||||
|
||||
hist1 = cv.calcHist([img1], [0], None, [num_bins], [0, 255])
|
||||
hist2 = cv.calcHist([img2], [0], None, [num_bins], [0, 255])
|
||||
sum = 0
|
||||
for i in range(num_bins):
|
||||
sum += abs(hist1[i] - hist2[i])
|
||||
return sum / float(width * height)
|
||||
|
||||
|
||||
def color_layout_descriptor(image, num_blocks=8, resize_to_px=256):
|
||||
resized_image = cv.resize(image, (resize_to_px, resize_to_px))
|
||||
ycrcb_image = cv.cvtColor(resized_image, cv.COLOR_BGR2YCrCb)
|
||||
|
||||
# Step 5: Divide the image into sub-blocks
|
||||
block_size = int(256 / num_blocks)
|
||||
blocks = []
|
||||
for i in range(num_blocks):
|
||||
for j in range(num_blocks):
|
||||
block = ycrcb_image[
|
||||
i * block_size : (i + 1) * block_size,
|
||||
j * block_size : (j + 1) * block_size,
|
||||
]
|
||||
blocks.append(block)
|
||||
|
||||
# Step 6: Extract features from each sub-block
|
||||
features = []
|
||||
for block in blocks:
|
||||
# Compute the mean and standard deviation of each color channel
|
||||
mean_y, mean_cr, mean_cb = np.mean(block, axis=(0, 1))
|
||||
std_y, std_cr, std_cb = np.std(block, axis=(0, 1))
|
||||
features.extend([mean_y, mean_cr, mean_cb, std_y, std_cr, std_cb])
|
||||
|
||||
# Step 7: Concatenate features into a single vector
|
||||
cld_vector = np.array(features)
|
||||
|
||||
return cld_vector
|
||||
|
||||
|
||||
def colorlayoutCompare(cld1, cld2):
|
||||
distance = np.linalg.norm(cld1 - cld2)
|
||||
|
||||
similarity = 1.0 / (1.0 + distance)
|
||||
|
||||
return (distance, similarity)
|
||||
|
||||
|
||||
def retrieval(choice="3"):
|
||||
print("testing retrieval ...")
|
||||
# print("1: beach")
|
||||
# print("2: building")
|
||||
# print("3: bus")
|
||||
# print("4: dinosaur")
|
||||
# print("5: flower")
|
||||
# print("6: horse")
|
||||
# print("7: man")
|
||||
|
||||
# choice = input("Type in the number to choose a category and type enter to confirm\n")
|
||||
|
||||
if choice == "1":
|
||||
img_input = cv.imread("beach.jpg")
|
||||
print("test: %s - beach" % choice)
|
||||
if choice == "2":
|
||||
img_input = cv.imread("building.jpg")
|
||||
print("test: %s - building" % choice)
|
||||
if choice == "3":
|
||||
img_input = cv.imread("bus.jpg")
|
||||
print("test: %s - bus" % choice)
|
||||
if choice == "4":
|
||||
img_input = cv.imread("dinosaur.jpg")
|
||||
print("test: %s - dinosaur" % choice)
|
||||
if choice == "5":
|
||||
img_input = cv.imread("flower.jpg")
|
||||
print("test: %s - flower" % choice)
|
||||
if choice == "6":
|
||||
img_input = cv.imread("horse.jpg")
|
||||
print("test: %s - horse" % choice)
|
||||
if choice == "7":
|
||||
img_input = cv.imread("man.jpg")
|
||||
print("test: %s - man" % choice)
|
||||
|
||||
min_diff = 1e50
|
||||
# src_input = cv.imread("man.jpg")
|
||||
# cv.imshow("Input", img_input)
|
||||
# change the image to gray scale
|
||||
# src_gray = cv.cvtColor(img_input, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# read image database
|
||||
database = sorted(glob(database_dir + "/*.jpg"))
|
||||
|
||||
diff_array = []
|
||||
|
||||
cld1 = color_layout_descriptor(img_input)
|
||||
for img in database:
|
||||
print(f"processing {img}", end="\r")
|
||||
|
||||
# read image
|
||||
img_rgb = cv.imread(img)
|
||||
cld2 = color_layout_descriptor(img_rgb)
|
||||
|
||||
# compare the two images
|
||||
# diff = compareImgs(img_input, img_rgb)
|
||||
(d, s) = colorlayoutCompare(cld1, cld2)
|
||||
diff = d
|
||||
|
||||
# compare the two images by histogram, uncomment the following line to use histogram
|
||||
# diff = compareImgs_hist(src_gray, img_gray)
|
||||
# print(img, diff)
|
||||
diff_array.append([img, diff, img_rgb])
|
||||
|
||||
print("")
|
||||
diff_array.sort(key=lambda x: x[1])
|
||||
result = diff_array[0]
|
||||
min_diff = result[1]
|
||||
closest_img = result[2]
|
||||
|
||||
# get feature match
|
||||
diff_with_matches = []
|
||||
i = 0
|
||||
for diff in diff_array[0:20]:
|
||||
i += 1
|
||||
# SIFT_debug(img_input, diff[2])
|
||||
full_file_name = diff[0]
|
||||
img = diff[2]
|
||||
|
||||
filename_only = full_file_name.replace("image.orig/", "")
|
||||
category = filename_only[0]
|
||||
len_good_matches = SIFT_compare(img_input, img)
|
||||
|
||||
diff_with_matches.append([full_file_name, len_good_matches, d, img])
|
||||
|
||||
matches = sorted(diff_with_matches, key=lambda x: x[1], reverse=True)
|
||||
for match in matches:
|
||||
pprint((match[0], match[1], match[2]))
|
||||
|
||||
[full_file_name, len_good_matches, d, closest_img] = matches[0]
|
||||
|
||||
# print("the most similar image is %s, the pixel-by-pixel difference is %f " % (result, min_diff))
|
||||
# print("\n")
|
||||
|
||||
cv.imshow("Result", closest_img)
|
||||
# cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
|
||||
filename_only = full_file_name.replace("image.orig/", "")
|
||||
category = filename_only[0]
|
||||
|
||||
print("f:" + filename_only + ": c:" + category)
|
||||
|
||||
return category
|
||||
|
||||
|
||||
def SIFT():
|
||||
img1 = cv.imread("flower.jpg")
|
||||
img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
# -- Show detected matches
|
||||
cv.imshow("Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
cv.imshow("Good Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
|
||||
def SIFT_debug(img1, img2):
|
||||
# img1 = cv.imread("flower.jpg")
|
||||
# img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
# -- Show detected matches
|
||||
cv.imshow("Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
cv.imshow("Good Matches: SIFT (Python)", img_matches)
|
||||
cv.waitKey()
|
||||
|
||||
|
||||
def SIFT_compare(img1, img2):
|
||||
# img1 = cv.imread("flower.jpg")
|
||||
# img2 = cv.imread("image.orig/685.jpg")
|
||||
if img1 is None or img2 is None:
|
||||
print("Error loading images!")
|
||||
exit(0)
|
||||
# -- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
|
||||
minHessian = 400
|
||||
detector = cv.SIFT_create()
|
||||
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
|
||||
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
|
||||
# -- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
|
||||
matches = matcher.match(descriptors1, descriptors2)
|
||||
|
||||
# -- Draw matches
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
# cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
|
||||
|
||||
# -- Show detected matches
|
||||
# cv.imshow('Matches: SIFT (Python)', img_matches)
|
||||
# cv.waitKey()
|
||||
|
||||
# draw good matches
|
||||
matches = sorted(matches, key=lambda x: x.distance)
|
||||
min_dist = matches[0].distance
|
||||
good_matches = tuple(filter(lambda x: x.distance <= 2 * min_dist, matches))
|
||||
|
||||
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1] + img2.shape[1], 3), dtype=np.uint8)
|
||||
|
||||
# cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
|
||||
|
||||
# -- Show detected matches
|
||||
# cv.imshow('Good Matches: SIFT (Python)', img_matches)
|
||||
# cv.waitKey()
|
||||
return len(good_matches)
|
||||
|
||||
|
||||
def test():
|
||||
test_result = True
|
||||
# 1, 2, 4, 7
|
||||
for i in [5]:
|
||||
if str(i) == retrieval(str(i)):
|
||||
print("test ok")
|
||||
else:
|
||||
test_result = False
|
||||
|
||||
if test_result:
|
||||
print("all test ok")
|
||||
pass
|
||||
else:
|
||||
print("some test failed")
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
test()
|
||||
sys.exit()
|
||||
|
||||
print("1: Image retrieval demo")
|
||||
print("2: SIFT demo")
|
||||
number = int(input("Type in the number to choose a demo and type enter to confirm\n"))
|
||||
|
||||
if number == 1:
|
||||
retrieval()
|
||||
elif number == 2:
|
||||
SIFT()
|
||||
# pass
|
||||
else:
|
||||
print("Invalid input")
|
||||
exit()
|
||||
|
||||
|
||||
main()
|
1001
vinniesniper-54816/task1/_ref/2022-Codes-Python/descriptor.csv
Normal file
1001
vinniesniper-54816/task1/_ref/2022-Codes-Python/descriptor.csv
Normal file
File diff suppressed because it is too large
Load Diff
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/descriptor.xlsx
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/descriptor.xlsx
Normal file
Binary file not shown.
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/dinosaur.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/dinosaur.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/flower.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/flower.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/horse.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/horse.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/000.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/000.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/001.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/001.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/002.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/002.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/003.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/003.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/004.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/004.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/005.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/005.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/006.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/006.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/007.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/007.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/008.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/008.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/009.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/009.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/010.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/010.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/011.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/011.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/012.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/012.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/013.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/013.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/014.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/014.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/015.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/015.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/016.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/016.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/017.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/017.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/018.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/018.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/019.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/019.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/020.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/020.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/021.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/021.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/022.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/022.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/023.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/023.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/024.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/024.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/025.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/025.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/026.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/026.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/027.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/027.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/028.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/028.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/029.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/029.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/030.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/030.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/031.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/031.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/032.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/032.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/033.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/033.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/034.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/034.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/035.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/035.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/036.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/036.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/037.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/037.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/038.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/038.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/039.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/039.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/040.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/040.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/041.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/041.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/042.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/042.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/043.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/043.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/044.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/044.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/045.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/045.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/046.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/046.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/047.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/047.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/048.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/048.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/049.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/049.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/050.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/050.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/051.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/051.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/052.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/052.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/053.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/053.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/054.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/054.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/055.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/055.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/056.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/056.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/057.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/057.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/058.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/058.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/059.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/059.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/060.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/060.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/061.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/061.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/062.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/062.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/063.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/063.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/064.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/064.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/065.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/065.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/066.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/066.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/067.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/067.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/068.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/068.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/069.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/069.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/070.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/070.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/071.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/071.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/072.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/072.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/073.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/073.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/074.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/074.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/075.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/075.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/076.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/076.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/077.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/077.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/078.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/078.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/079.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/079.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/080.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/080.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/081.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/081.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/082.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/082.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/083.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/083.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/084.jpg
(Stored with Git LFS)
Normal file
BIN
vinniesniper-54816/task1/_ref/2022-Codes-Python/image.orig/084.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user