├── README.md ├── hough.py ├── orb.py └── sift.py /README.md: -------------------------------------------------------------------------------- 1 | # Thermal To Visible Registration 2 | Install the dependencies 3 | - opencv 4 | - numpy 5 | - imutils 6 | 7 | # folders to be created to get the output images 8 | - output_orb 9 | - output_sift 10 | - output_hough 11 | - results_orb 12 | - results_sift 13 | - results_hough 14 | - registration_orb 15 | - registration_sift 16 | - registration_hough 17 | - uncropped_orb 18 | - uncropped_sift 19 | - uncropped_hough 20 | - thermal 21 | - visible 22 | # How To Run ? 23 | - Add the thermal and it's corresponding visible image in the foler `thermal` and `visible` folder respectively in the same order, 1st image in visible folder should be the corresponding thermal image of the 1st image in the thermal folder 24 | - make sure you have created the mentioned folders 25 | - To run the registration using ORB feature matching run `python orb.py`. The results will be saved in the folders with _orb 26 | - To run the registration using SIFT feature matching run `python sift.py`. The results will be saved in the folders with _sift 27 | - To run the registration using HOUGH feature matching run `python hough.py`. The results will be saved in the folders with _hough 28 | - The folders named results and uncropped are the final outputs after registration. 29 | 30 | To know more about how the project works go through this [article](https://medium.com/@aswinvb/how-to-perform-thermal-to-visible-image-registration-c18a34894866) 31 | -------------------------------------------------------------------------------- /hough.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import numpy as np 3 | import argparse 4 | import imutils 5 | import glob 6 | import cv2 7 | import os 8 | 9 | MAX_FEATURES = 500 10 | GOOD_MATCH_PERCENT = 0.15 11 | MIN_MATCH_COUNT = 50 12 | 13 | def alignImages(img1, img2,filename,_type): 14 | original = img1 15 | image_to_compare = img2 16 | sift = cv2.xfeatures2d.SIFT_create() 17 | kp_1, desc_1 = sift.detectAndCompute(original, None) 18 | kp_2, desc_2 = sift.detectAndCompute(image_to_compare, None) 19 | index_params = dict(algorithm=0, trees=5) 20 | search_params = dict() 21 | flann = cv2.FlannBasedMatcher(index_params, search_params) 22 | 23 | matches = flann.knnMatch(desc_1, desc_2, k=2) 24 | good_points = [] 25 | ratio = 0.6 26 | for m, n in matches: 27 | if m.distance < ratio*n.distance: 28 | good_points.append(m) 29 | print(len(good_points)) 30 | 31 | result = cv2.drawMatches(original, kp_1, image_to_compare, kp_2, good_points, None) 32 | # cv2.imshow("result", result) 33 | # cv2.imshow("Original", original) 34 | # cv2.imshow("Duplicate", image_to_compare) 35 | if _type=="cropped": 36 | cv2.imwrite(os.path.join('./registration_hough/',filename), result) 37 | else: 38 | cv2.imwrite(os.path.join('./uncropped_hough/',filename), result) 39 | 40 | print("Enter the required options : ") 41 | print("1) Automatic Registration on all images") 42 | print("2) Enter name of visible and thermal image yourself") 43 | option = int(input()) 44 | if(option==1): 45 | directory = 'thermal' 46 | thermal_images_files=[] 47 | for filename in os.listdir(directory): 48 | thermal_images_files.append(filename) 49 | directory = 'visible' 50 | visible_images_files=[] 51 | for filename in os.listdir(directory): 52 | visible_images_files.append(filename) 53 | 54 | 55 | for i in range(len(thermal_images_files)): 56 | try: 57 | filename='./results_hough/'+str(i)+'.jpg' 58 | if os.path.exists(filename): 59 | print("image already exists") 60 | continue 61 | else: 62 | print("performing registration") 63 | # load the image image, convert it to grayscale, and detect edges 64 | template = cv2.imread('thermal/'+thermal_images_files[i]) 65 | template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) 66 | template = cv2.Canny(template, 50, 200) 67 | (tH, tW) = template.shape[:2] 68 | 69 | # loop over the images to find the template in 70 | 71 | # load the image, convert it to grayscale, and initialize the 72 | # bookkeeping variable to keep track of the matched region 73 | image = cv2.imread('visible/'+visible_images_files[i]) 74 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 75 | found = None 76 | 77 | # loop over the scales of the image 78 | for scale in np.linspace(0.2, 1.0, 20)[::-1]: 79 | # resize the image according to the scale, and keep track 80 | # of the ratio of the resizing 81 | resized = imutils.resize(gray, width = int(gray.shape[1] * scale)) 82 | r = gray.shape[1] / float(resized.shape[1]) 83 | 84 | # if the resized image is smaller than the template, then break 85 | # from the loop 86 | if resized.shape[0] < tH or resized.shape[1] < tW: 87 | break 88 | 89 | # detect edges in the resized, grayscale image and apply template 90 | # matching to find the template in the image 91 | edged = cv2.Canny(resized, 50, 200) 92 | result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF) 93 | (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) 94 | 95 | # if we have found a new maximum correlation value, then update 96 | # the bookkeeping variable 97 | if found is None or maxVal > found[0]: 98 | found = (maxVal, maxLoc, r) 99 | 100 | # unpack the bookkeeping variable and compute the (x, y) coordinates 101 | # of the bounding box based on the resized ratio 102 | (_, maxLoc, r) = found 103 | (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r)) 104 | (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r)) 105 | 106 | # draw a bounding box around the detected result and display the image 107 | cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2) 108 | crop_img = image[startY:endY, startX:endX] 109 | 110 | name = "thermal/"+thermal_images_files[i] 111 | thermal_image = cv2.imread(name, cv2.IMREAD_COLOR) 112 | 113 | crop_img = cv2.resize(crop_img, (thermal_image.shape[1], thermal_image.shape[0])) 114 | 115 | cv2.imwrite(os.path.join('./output_hough/', str(i)+'.jpg'),crop_img) 116 | 117 | final = np.concatenate((crop_img, thermal_image), axis = 1) 118 | cv2.imwrite(os.path.join('./results_hough/', str(i)+'.jpg'),final) 119 | 120 | cv2.waitKey(0) 121 | 122 | # Read reference image 123 | refFilename = "thermal/"+thermal_images_files[i] 124 | print("Reading reference image : ", refFilename) 125 | imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR) 126 | 127 | # Read image to be aligned 128 | imFilename = "output_hough/"+str(i)+'.jpg' 129 | print("Reading image to align : ", imFilename); 130 | im = cv2.imread(imFilename, cv2.IMREAD_COLOR) 131 | file_name=thermal_images_files[i] 132 | alignImages(im,imReference,file_name,"cropped") 133 | alignImages(image,imReference,file_name,"uncropped") 134 | 135 | except: 136 | pass 137 | 138 | else: 139 | print("Enter the name of thermal image in thermal folder") 140 | thermal = raw_input() 141 | print("Enter the name of visible image in visible folder") 142 | visible = raw_input() 143 | image = cv2.imread('visible/'+visible+'.jpg') 144 | template = cv2.imread('thermal/'+thermal+'.jpg') 145 | 146 | print("performing registration") 147 | # load the image image, convert it to grayscale, and detect edges 148 | template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) 149 | template = cv2.Canny(template, 50, 200) 150 | (tH, tW) = template.shape[:2] 151 | 152 | # loop over the images to find the template in 153 | 154 | # load the image, convert it to grayscale, and initialize the 155 | # bookkeeping variable to keep track of the matched region 156 | image = cv2.imread('visible/'+visible+'.jpg') 157 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 158 | found = None 159 | 160 | # loop over the scales of the image 161 | for scale in np.linspace(0.2, 1.0, 20)[::-1]: 162 | # resize the image according to the scale, and keep track 163 | # of the ratio of the resizing 164 | resized = imutils.resize(gray, width = int(gray.shape[1] * scale)) 165 | r = gray.shape[1] / float(resized.shape[1]) 166 | 167 | # if the resized image is smaller than the template, then break 168 | # from the loop 169 | if resized.shape[0] < tH or resized.shape[1] < tW: 170 | break 171 | 172 | # detect edges in the resized, grayscale image and apply template 173 | # matching to find the template in the image 174 | edged = cv2.Canny(resized, 50, 200) 175 | result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF) 176 | (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) 177 | 178 | # if we have found a new maximum correlation value, then update 179 | # the bookkeeping variable 180 | if found is None or maxVal > found[0]: 181 | found = (maxVal, maxLoc, r) 182 | 183 | # unpack the bookkeeping variable and compute the (x, y) coordinates 184 | # of the bounding box based on the resized ratio 185 | (_, maxLoc, r) = found 186 | (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r)) 187 | (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r)) 188 | 189 | # draw a bounding box around the detected result and display the image 190 | cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2) 191 | crop_img = image[startY:endY, startX:endX] 192 | 193 | name = "thermal/"+thermal+'.jpg' 194 | thermal_image = cv2.imread(name, cv2.IMREAD_COLOR) 195 | 196 | crop_img = cv2.resize(crop_img, (thermal_image.shape[1], thermal_image.shape[0])) 197 | 198 | cv2.imwrite(os.path.join('./output_hough/', thermal+'.jpg'),crop_img) 199 | 200 | final = np.concatenate((crop_img, thermal_image), axis = 1) 201 | cv2.imwrite(os.path.join('./results_hough/', thermal+'.jpg'),final) 202 | 203 | cv2.waitKey(0) 204 | 205 | # Read reference image 206 | refFilename = "thermal/"+thermal+'.jpg' 207 | print("Reading reference image : ", refFilename) 208 | imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR) 209 | 210 | # Read image to be aligned 211 | imFilename = "output_hough/"+thermal+'.jpg' 212 | print("Reading image to align : ", imFilename); 213 | im = cv2.imread(imFilename, cv2.IMREAD_COLOR) 214 | file_name=thermal+'.jpg' 215 | alignImages(im,imReference,file_name,"cropped") 216 | alignImages(image,imReference,file_name,"uncropped") -------------------------------------------------------------------------------- /orb.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import numpy as np 3 | import argparse 4 | import imutils 5 | import glob 6 | import cv2 7 | import os 8 | 9 | MAX_FEATURES = 500 10 | GOOD_MATCH_PERCENT = 0.15 11 | 12 | def alignImages(im1, im2,filename,_type): 13 | 14 | # Convert images to grayscale 15 | im1Gray = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY) 16 | im2Gray = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY) 17 | 18 | # Detect ORB features and compute descriptors. 19 | orb = cv2.ORB_create(MAX_FEATURES) 20 | keypoints1, descriptors1 = orb.detectAndCompute(im1Gray, None) 21 | keypoints2, descriptors2 = orb.detectAndCompute(im2Gray, None) 22 | 23 | # Match features. 24 | matcher = cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING) 25 | matches = matcher.match(descriptors1, descriptors2, None) 26 | 27 | # Sort matches by score 28 | matches.sort(key=lambda x: x.distance, reverse=False) 29 | 30 | # Remove not so good matches 31 | numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT) 32 | matches = matches[:numGoodMatches] 33 | 34 | # Draw top matches 35 | imMatches = cv2.drawMatches(im1, keypoints1, im2, keypoints2, matches, None) 36 | if _type=="cropped": 37 | cv2.imwrite(os.path.join('./registration_orb/',filename), imMatches) 38 | else: 39 | cv2.imwrite(os.path.join('./uncropped_orb/',filename), imMatches) 40 | # Extract location of good matches 41 | points1 = np.zeros((len(matches), 2), dtype=np.float32) 42 | points2 = np.zeros((len(matches), 2), dtype=np.float32) 43 | 44 | for i, match in enumerate(matches): 45 | points1[i, :] = keypoints1[match.queryIdx].pt 46 | points2[i, :] = keypoints2[match.trainIdx].pt 47 | 48 | # Find homography 49 | h, mask = cv2.findHomography(points1, points2, cv2.RANSAC) 50 | 51 | # Use homography 52 | height, width, channels = im2.shape 53 | im1Reg = cv2.warpPerspective(im1, h, (width, height)) 54 | 55 | return im1Reg, h 56 | 57 | print("Enter the required options : ") 58 | print("1) Automatic Registration on all images") 59 | print("2) Enter name of visible and thermal image yourself") 60 | option = int(input()) 61 | if(option==1): 62 | directory = 'thermal' 63 | thermal_images_files=[] 64 | for filename in os.listdir(directory): 65 | thermal_images_files.append(filename) 66 | directory = 'visible' 67 | visible_images_files=[] 68 | for filename in os.listdir(directory): 69 | visible_images_files.append(filename) 70 | 71 | 72 | for i in range(len(thermal_images_files)): 73 | try: 74 | filename='./results_orb/'+str(i)+'.jpg' 75 | if os.path.exists(filename): 76 | print("image already exists") 77 | continue 78 | else: 79 | print("performing registration") 80 | # load the image image, convert it to grayscale, and detect edges 81 | template = cv2.imread('thermal/'+thermal_images_files[i]) 82 | template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) 83 | template = cv2.Canny(template, 50, 200) 84 | (tH, tW) = template.shape[:2] 85 | 86 | # loop over the images to find the template in 87 | 88 | # load the image, convert it to grayscale, and initialize the 89 | # bookkeeping variable to keep track of the matched region 90 | image = cv2.imread('visible/'+visible_images_files[i]) 91 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 92 | found = None 93 | 94 | # loop over the scales of the image 95 | for scale in np.linspace(0.2, 1.0, 20)[::-1]: 96 | # resize the image according to the scale, and keep track 97 | # of the ratio of the resizing 98 | resized = imutils.resize(gray, width = int(gray.shape[1] * scale)) 99 | r = gray.shape[1] / float(resized.shape[1]) 100 | 101 | # if the resized image is smaller than the template, then break 102 | # from the loop 103 | if resized.shape[0] < tH or resized.shape[1] < tW: 104 | break 105 | 106 | # detect edges in the resized, grayscale image and apply template 107 | # matching to find the template in the image 108 | edged = cv2.Canny(resized, 50, 200) 109 | result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF) 110 | (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) 111 | 112 | # if we have found a new maximum correlation value, then update 113 | # the bookkeeping variable 114 | if found is None or maxVal > found[0]: 115 | found = (maxVal, maxLoc, r) 116 | 117 | # unpack the bookkeeping variable and compute the (x, y) coordinates 118 | # of the bounding box based on the resized ratio 119 | (_, maxLoc, r) = found 120 | (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r)) 121 | (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r)) 122 | 123 | # draw a bounding box around the detected result and display the image 124 | cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2) 125 | crop_img = image[startY:endY, startX:endX] 126 | 127 | name = "thermal/"+thermal_images_files[i] 128 | thermal_image = cv2.imread(name, cv2.IMREAD_COLOR) 129 | 130 | crop_img = cv2.resize(crop_img, (thermal_image.shape[1], thermal_image.shape[0])) 131 | 132 | cv2.imwrite(os.path.join('./output_orb/', str(i)+'.jpg'),crop_img) 133 | 134 | final = np.concatenate((crop_img, thermal_image), axis = 1) 135 | cv2.imwrite(os.path.join('./results_orb/', str(i)+'.jpg'),final) 136 | 137 | cv2.waitKey(0) 138 | 139 | # Read reference image 140 | refFilename = "thermal/"+thermal_images_files[i] 141 | print("Reading reference image : ", refFilename) 142 | imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR) 143 | 144 | # Read image to be aligned 145 | imFilename = "output_orb/"+str(i)+'.jpg' 146 | print("Reading image to align : ", imFilename); 147 | im = cv2.imread(imFilename, cv2.IMREAD_COLOR) 148 | file_name=thermal_images_files[i] 149 | imReg, h = alignImages(im,imReference,file_name,"cropped") 150 | print("Estimated homography : \n", h) 151 | imReg, h = alignImages(image,imReference,file_name,"uncropped") 152 | 153 | except: 154 | pass 155 | 156 | else: 157 | print("Enter the name of thermal image in thermal folder") 158 | thermal = raw_input() 159 | print("Enter the name of visible image in visible folder") 160 | visible = raw_input() 161 | image = cv2.imread('visible/'+visible+'.jpg') 162 | template = cv2.imread('thermal/'+thermal+'.jpg') 163 | 164 | print("performing registration") 165 | # load the image image, convert it to grayscale, and detect edges 166 | template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) 167 | template = cv2.Canny(template, 50, 200) 168 | (tH, tW) = template.shape[:2] 169 | 170 | # loop over the images to find the template in 171 | 172 | # load the image, convert it to grayscale, and initialize the 173 | # bookkeeping variable to keep track of the matched region 174 | image = cv2.imread('visible/'+visible+'.jpg') 175 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 176 | found = None 177 | 178 | # loop over the scales of the image 179 | for scale in np.linspace(0.2, 1.0, 20)[::-1]: 180 | # resize the image according to the scale, and keep track 181 | # of the ratio of the resizing 182 | resized = imutils.resize(gray, width = int(gray.shape[1] * scale)) 183 | r = gray.shape[1] / float(resized.shape[1]) 184 | 185 | # if the resized image is smaller than the template, then break 186 | # from the loop 187 | if resized.shape[0] < tH or resized.shape[1] < tW: 188 | break 189 | 190 | # detect edges in the resized, grayscale image and apply template 191 | # matching to find the template in the image 192 | edged = cv2.Canny(resized, 50, 200) 193 | result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF) 194 | (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) 195 | 196 | # if we have found a new maximum correlation value, then update 197 | # the bookkeeping variable 198 | if found is None or maxVal > found[0]: 199 | found = (maxVal, maxLoc, r) 200 | 201 | # unpack the bookkeeping variable and compute the (x, y) coordinates 202 | # of the bounding box based on the resized ratio 203 | (_, maxLoc, r) = found 204 | (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r)) 205 | (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r)) 206 | 207 | # draw a bounding box around the detected result and display the image 208 | cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2) 209 | crop_img = image[startY:endY, startX:endX] 210 | 211 | name = "thermal/"+thermal+'.jpg' 212 | thermal_image = cv2.imread(name, cv2.IMREAD_COLOR) 213 | 214 | crop_img = cv2.resize(crop_img, (thermal_image.shape[1], thermal_image.shape[0])) 215 | 216 | cv2.imwrite(os.path.join('./output_orb/', thermal+'.jpg'),crop_img) 217 | 218 | final = np.concatenate((crop_img, thermal_image), axis = 1) 219 | cv2.imwrite(os.path.join('./results_orb/', thermal+'.jpg'),final) 220 | 221 | cv2.waitKey(0) 222 | 223 | # Read reference image 224 | refFilename = "thermal/"+thermal+'.jpg' 225 | print("Reading reference image : ", refFilename) 226 | imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR) 227 | 228 | # Read image to be aligned 229 | imFilename = "output_orb/"+thermal+'.jpg' 230 | print("Reading image to align : ", imFilename); 231 | im = cv2.imread(imFilename, cv2.IMREAD_COLOR) 232 | file_name=thermal+'.jpg' 233 | imReg, h = alignImages(im,imReference,file_name,"cropped") 234 | print("Estimated homography : \n", h) 235 | imReg, h = alignImages(image,imReference,file_name,"uncropped") -------------------------------------------------------------------------------- /sift.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import numpy as np 3 | import argparse 4 | import imutils 5 | import glob 6 | import cv2 7 | import os 8 | 9 | MAX_FEATURES = 500 10 | GOOD_MATCH_PERCENT = 0.15 11 | MIN_MATCH_COUNT = 50 12 | 13 | def alignImages(img1, img2,filename,_type): 14 | print("hi") 15 | # Initiate SIFT detector 16 | # sift = cv2.SIFT() 17 | sift = cv2.xfeatures2d.SIFT_create() 18 | # find the keypoints and descriptors with SIFT 19 | kp1, des1 = sift.detectAndCompute(img1,None) 20 | kp2, des2 = sift.detectAndCompute(img2,None) 21 | FLANN_INDEX_KDTREE = 0 22 | index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) 23 | search_params = dict(checks = 50) 24 | flann = cv2.FlannBasedMatcher(index_params, search_params) 25 | matches = flann.knnMatch(des1,des2,k=2) 26 | # store all the good matches as per Lowe's ratio test. 27 | good = [] 28 | for m,n in matches: 29 | if m.distance < 0.7*n.distance: 30 | good.append(m) 31 | if len(good)>MIN_MATCH_COUNT: 32 | src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2) 33 | dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2) 34 | M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0) 35 | matchesMask = mask.ravel().tolist() 36 | h,w = img1.shape[:-1] 37 | pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2) 38 | dst = cv2.perspectiveTransform(pts,M) 39 | img2 = cv2.polylines(img2,[np.int32(dst)],True,255,3, cv2.LINE_AA) 40 | else: 41 | matchesMask = None 42 | draw_params = dict(matchColor = (0,255,0), # draw matches in green color 43 | singlePointColor = None, 44 | matchesMask = matchesMask, # draw only inliers 45 | flags = 2) 46 | img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params) 47 | if _type=="cropped": 48 | cv2.imwrite(os.path.join('./registration_sift/',filename), img3) 49 | else: 50 | cv2.imwrite(os.path.join('./uncropped_sift/',filename), img3) 51 | 52 | print("Enter the required options : ") 53 | print("1) Automatic Registration on all images") 54 | print("2) Enter name of visible and thermal image yourself") 55 | option = int(input()) 56 | if(option==1): 57 | directory = 'thermal' 58 | thermal_images_files=[] 59 | for filename in os.listdir(directory): 60 | thermal_images_files.append(filename) 61 | directory = 'visible' 62 | visible_images_files=[] 63 | for filename in os.listdir(directory): 64 | visible_images_files.append(filename) 65 | 66 | 67 | for i in range(len(thermal_images_files)): 68 | try: 69 | filename='./results_sift/'+str(i)+'.jpg' 70 | if os.path.exists(filename): 71 | print("image already exists") 72 | continue 73 | else: 74 | print("performing registration") 75 | # load the image image, convert it to grayscale, and detect edges 76 | template = cv2.imread('thermal/'+thermal_images_files[i]) 77 | template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) 78 | template = cv2.Canny(template, 50, 200) 79 | (tH, tW) = template.shape[:2] 80 | 81 | # loop over the images to find the template in 82 | 83 | # load the image, convert it to grayscale, and initialize the 84 | # bookkeeping variable to keep track of the matched region 85 | image = cv2.imread('visible/'+visible_images_files[i]) 86 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 87 | found = None 88 | 89 | # loop over the scales of the image 90 | for scale in np.linspace(0.2, 1.0, 20)[::-1]: 91 | # resize the image according to the scale, and keep track 92 | # of the ratio of the resizing 93 | resized = imutils.resize(gray, width = int(gray.shape[1] * scale)) 94 | r = gray.shape[1] / float(resized.shape[1]) 95 | 96 | # if the resized image is smaller than the template, then break 97 | # from the loop 98 | if resized.shape[0] < tH or resized.shape[1] < tW: 99 | break 100 | 101 | # detect edges in the resized, grayscale image and apply template 102 | # matching to find the template in the image 103 | edged = cv2.Canny(resized, 50, 200) 104 | result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF) 105 | (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) 106 | 107 | # if we have found a new maximum correlation value, then update 108 | # the bookkeeping variable 109 | if found is None or maxVal > found[0]: 110 | found = (maxVal, maxLoc, r) 111 | 112 | # unpack the bookkeeping variable and compute the (x, y) coordinates 113 | # of the bounding box based on the resized ratio 114 | (_, maxLoc, r) = found 115 | (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r)) 116 | (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r)) 117 | 118 | # draw a bounding box around the detected result and display the image 119 | cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2) 120 | crop_img = image[startY:endY, startX:endX] 121 | 122 | name = "thermal/"+thermal_images_files[i] 123 | thermal_image = cv2.imread(name, cv2.IMREAD_COLOR) 124 | 125 | crop_img = cv2.resize(crop_img, (thermal_image.shape[1], thermal_image.shape[0])) 126 | 127 | cv2.imwrite(os.path.join('./output_sift/', str(i)+'.jpg'),crop_img) 128 | 129 | final = np.concatenate((crop_img, thermal_image), axis = 1) 130 | cv2.imwrite(os.path.join('./results_sift/', str(i)+'.jpg'),final) 131 | 132 | cv2.waitKey(0) 133 | 134 | # Read reference image 135 | refFilename = "thermal/"+thermal_images_files[i] 136 | print("Reading reference image : ", refFilename) 137 | imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR) 138 | 139 | # Read image to be aligned 140 | imFilename = "output_sift/"+str(i)+'.jpg' 141 | print("Reading image to align : ", imFilename); 142 | im = cv2.imread(imFilename, cv2.IMREAD_COLOR) 143 | file_name=thermal_images_files[i] 144 | alignImages(im,imReference,file_name,"cropped") 145 | alignImages(image,imReference,file_name,"uncropped") 146 | 147 | except: 148 | pass 149 | 150 | else: 151 | print("Enter the name of thermal image in thermal folder") 152 | thermal = raw_input() 153 | print("Enter the name of visible image in visible folder") 154 | visible = raw_input() 155 | image = cv2.imread('visible/'+visible+'.jpg') 156 | template = cv2.imread('thermal/'+thermal+'.jpg') 157 | 158 | print("performing registration") 159 | # load the image image, convert it to grayscale, and detect edges 160 | template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) 161 | template = cv2.Canny(template, 50, 200) 162 | (tH, tW) = template.shape[:2] 163 | 164 | # loop over the images to find the template in 165 | 166 | # load the image, convert it to grayscale, and initialize the 167 | # bookkeeping variable to keep track of the matched region 168 | image = cv2.imread('visible/'+visible+'.jpg') 169 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 170 | found = None 171 | 172 | # loop over the scales of the image 173 | for scale in np.linspace(0.2, 1.0, 20)[::-1]: 174 | # resize the image according to the scale, and keep track 175 | # of the ratio of the resizing 176 | resized = imutils.resize(gray, width = int(gray.shape[1] * scale)) 177 | r = gray.shape[1] / float(resized.shape[1]) 178 | 179 | # if the resized image is smaller than the template, then break 180 | # from the loop 181 | if resized.shape[0] < tH or resized.shape[1] < tW: 182 | break 183 | 184 | # detect edges in the resized, grayscale image and apply template 185 | # matching to find the template in the image 186 | edged = cv2.Canny(resized, 50, 200) 187 | result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF) 188 | (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) 189 | 190 | # if we have found a new maximum correlation value, then update 191 | # the bookkeeping variable 192 | if found is None or maxVal > found[0]: 193 | found = (maxVal, maxLoc, r) 194 | 195 | # unpack the bookkeeping variable and compute the (x, y) coordinates 196 | # of the bounding box based on the resized ratio 197 | (_, maxLoc, r) = found 198 | (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r)) 199 | (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r)) 200 | 201 | # draw a bounding box around the detected result and display the image 202 | cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2) 203 | crop_img = image[startY:endY, startX:endX] 204 | 205 | name = "thermal/"+thermal+'.jpg' 206 | thermal_image = cv2.imread(name, cv2.IMREAD_COLOR) 207 | 208 | crop_img = cv2.resize(crop_img, (thermal_image.shape[1], thermal_image.shape[0])) 209 | 210 | cv2.imwrite(os.path.join('./output_sift/', thermal+'.jpg'),crop_img) 211 | 212 | final = np.concatenate((crop_img, thermal_image), axis = 1) 213 | cv2.imwrite(os.path.join('./results_sift/', thermal+'.jpg'),final) 214 | 215 | cv2.waitKey(0) 216 | 217 | # Read reference image 218 | refFilename = "thermal/"+thermal+'.jpg' 219 | print("Reading reference image : ", refFilename) 220 | imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR) 221 | 222 | # Read image to be aligned 223 | imFilename = "output_sift/"+thermal+'.jpg' 224 | print("Reading image to align : ", imFilename); 225 | im = cv2.imread(imFilename, cv2.IMREAD_COLOR) 226 | file_name=thermal+'.jpg' 227 | alignImages(im,imReference,file_name,"cropped") 228 | alignImages(image,imReference,file_name,"uncropped") --------------------------------------------------------------------------------