csv file uploaded to s3 using boto3 is empty in s3 - python
I have two csv files that i am uploading from an ec2 instance to the s3 bucket along with a few other files. All the other files are being uploaded just fine but my csv files, though it is uploaded, there seems ot be no data inside it even though the local copy of the file on the instance is showing the data. im not sure why its saying 0 bytes on the bucket.
the csv file is part of another larger program. here is the code.
from boto3.session import Session
import botocore
import boto3
import zipfile
import darknet
import os
import cv2
import glob
import csv
import numpy as np
global lat_start, lon_start
import shutil
#HELPER FUNCTION DEFINITIONS
ACCESS_KEY = '*********'
SECRET_KEY = '******D'
def image_detection(image_path, network, class_names, class_colors, thresh):
# Darknet doesn't accept numpy images.
# Create one with image we reuse for each detect
width = darknet.network_width(network)
height = darknet.network_height(network)
darknet_image = darknet.make_image(width, height, 3)
image = cv2.imread(image_path)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image_resized = cv2.resize(image_rgb, (width, height),interpolation=cv2.INTER_LINEAR)
darknet.copy_image_from_bytes(darknet_image, image_resized.tobytes())
detections = darknet.detect_image(network, class_names, darknet_image, thresh=thresh)
darknet.free_image(darknet_image)
image = darknet.draw_boxes(detections, image_resized, class_colors)
return cv2.cvtColor(image, cv2.COLOR_BGR2RGB), detections
def discretize_line(lat_start, lon_start, d_element, d, bearing):
# d_element -> how many element we need in a line secment
# global lat_start, lon_start
R = 6371.0*1000.0
# -1 because in case of 10 elements/points we also want len(lat_array) the same
dstep = d/(d_element-1) #0.6524896365354135 #2.0 # meters
dist_list = np.ones(int(d/dstep))*dstep
# print(dist_list)
brg = np.radians(bearing)
# if d%dstep != 0:
# dist_list = np.append(dist_list, d%dstep)
# This will append lat and lon into array which contains
# small segments of distance
lat_array = np.array([np.radians(lat_start)]) # rads
lon_array = np.array([np.radians(lon_start)]) # rads
# lat_array = np.array([])
# lon_array = np.array([])
for i, dist in enumerate(dist_list):
## last element make the waypoint shifted, so we break it
if i >= (d_element):
break
lat1 = lat_array[i]
lon1 = lon_array[i]
# print(dist)
Ad = dist/R
lat2 = np.arcsin(np.sin(lat1)*np.cos(Ad) + np.cos(lat1)*np.sin(Ad)*np.cos(brg))
lon2 = lon1 + np.arctan2( (np.sin(brg)*np.sin(Ad)*np.cos(lat1)) , (np.cos(Ad) - np.sin(lat1)*np.sin(lat2)))
lat_array = np.append(lat_array, lat2)
lon_array = np.append(lon_array, lon2)
# print(i)
return lat_array, lon_array
def get_distance_bearing(lat1, lon1, lat2, lon2):
# global lat_start, lon_start
R = 6371.0*1000.0
lat_start = np.radians(lat1)
lon_start = np.radians(lon1)
lat_end = np.radians(lat2)
lon_end = np.radians(lon2)
dLat = lat_end - lat_start
dLon = lon_end - lon_start
a = np.sin(dLat/2.0)*np.sin(dLat/2.0) + np.cos(lat_start)*np.cos(lat_end)*np.sin(dLon/2.0)*np.sin(dLon/2.0)
c = 2.0*np.arctan2(np.sqrt(a),np.sqrt(1-a))
d = c*R
y = np.sin(dLon)*np.cos(lat_end)
x = np.cos(lat_start)*np.sin(lat_end) - np.sin(lat_start)*np.cos(lat_end)*np.cos(dLon)
bearing = np.degrees(np.arctan2(y,x))
return d, bearing
def upload_to_aws(local_file, bucket, s3_file):
s3 = boto3.client('s3', aws_access_key_id=ACCESS_KEY,
aws_secret_access_key=SECRET_KEY)
try:
s3.upload_file(local_file, bucket, s3_file)
print("Upload Successful")
return True
except FileNotFoundError:
print("The file was not found")
return False
except NoCredentialsError:
print("Credentials not available")
return False
##END OF FUNCTION DEFINITIONS ##
#Unzip the zip file and its contents
print("unzipping")
path_to_zip_file = "/home/ubuntu/pano/Zip/Videos.zip"
with zipfile.ZipFile(path_to_zip_file, 'r') as zip_ref:
zip_ref.extractall("/home/ubuntu/pano/Video")
print("Finished Unzipping")
#End of Unzip
# CSV open and declaration##
data_file_path = "/home/ubuntu/pano/stack/quantity.csv"
data_file = open(data_file_path, "w+")
dataCSVWriter = csv.writer(data_file, delimiter=',',quotechar='|', quoting=csv.QUOTE_MINIMAL)
dataCSVWriter.writerow(['lat', 'lon', 'Quantity'])
#CSV for lane thumbnail
thumbnail_data_file_path = "/home/ubuntu/pano/stack/lane_thumbnail.csv"
thumbnail_data_file = open(thumbnail_data_file_path, "w+")
thumbnail_dataCSVWriter = csv.writer(thumbnail_data_file, delimiter=',',quotechar='|', quoting=csv.QUOTE_MINIMAL)
thumbnail_dataCSVWriter.writerow(['lat', 'lon'])
#Define start and end point lists
#start_point_list = [(35.841454251754755, 139.52427014959153),(35.84147944801779, 139.52420150963678)]
start_point_list = [(36.12083710338884, 139.21630320454503),(36.12080527337101, 139.2164926108044)]
#end_point_list = [(35.84151350159559, 139.52424466860762),(35.84144222040454, 139.52422739581436)]
end_point_list = [(36.12083735438514, 139.2164757318577),(36.12081575161991, 139.21630345327617)]
wp_lat_array = np.array([])
wp_lon_array = np.array([])
##Split th eline into points and it is stored in lat array lon array
"""for i in range(len(start_point_list)):
## input two points and find a slicing waypoint between it
distance, bearing_deg = get_distance_bearing(start_point_list[i][0], start_point_list[i][1], end_point_list[i][0], end_point_list[i][1])
print(distance)
lat_array, lon_array = discretize_line(start_point_list[i][0], start_point_list[i][1], float(d_element[i]), distance, bearing_deg)"""
#Initialize the detector variables and paths
quantity_bottles_frame = []
config_file = "/home/ubuntu/darknet_bottle_example/yolov4_bottle_can.cfg"
data_file = "/home/ubuntu/darknet_bottle_example/obj_bottle_can.data"
weights = "/home/ubuntu/darknet_bottle_example/yolov4_bottle_can_best.weights"
network, class_names, class_colors = darknet.load_network(
config_file,
data_file,
weights,
batch_size=1
)
image_dir = "/home/ubuntu/pano/Frames"
#1.Split into frames
path = "/home/ubuntu/pano/Video/Panorama/Videos"
j = 0
"""Order of events
1. Split into frames
2. Rotate images if needed
3. Running through detctor
4. Calculate count and draw bounding boxes
5. Store these images in respective directoies
6. Take start point of lane and end point and split into many coordinates in between based on number of frames
7. Write to csv file
8. Stack the images per lane
9. Empty the Frames folder after every lane
10. Upload stacked images and csv to cloud """
# Parameter to change is fps in the ffmpeg command. Change accoprding to need based on reference
for filename in os.listdir(path):
if (filename.endswith(".mp4")): #or .avi, .mpeg, whatever.
j += 1
path1 = path + filename
print(path1)
os.system("ffmpeg -i /home/ubuntu/pano/Video/Panorama/Videos/{0} -vf fps=0.07 /home/ubuntu/pano/Frames/{1}-%3d.jpg".format(filename,j))
#2. Rotate images if needed
frames_path = "/home/ubuntu/pano/Frames/*.jpg"
list_images = glob.glob(frames_path)
list_sorted = sorted(list_images)
#for image in list_sorted:
#read the image
# temp = cv2.imread(image)
# image1 = cv2.rotate(temp, cv2.ROTATE_90_COUNTERCLOCKWISE)
# cv2.imwrite("{0}".format(image), image1)
## according to how many partial panorama we have in each lane
d_element =[len(list_images)]
print(f"Now detecting objects in lane {j}")
#3. Running through detctor
frame_number = 1
for image in sorted(os.listdir(image_dir)):
#Path to the input images for the detector i.e Frames
quantity_frame = 0
image_name = f"{image}"
ext = '.jpg'
input_image_name = image_name
image_path = os.path.join(image_dir, input_image_name)
print(image_path)
#Path to output images to be stored after running through detector
output_dir = f"/home/ubuntu/pano/lane{j}"
output_name = "yolo_" + image_name
output_path = os.path.join(output_dir, output_name)
# image = load_images(image_path)
dn_frame_width = 416
dn_frame_height = 416
frame = cv2.imread(image_path)
frame_width = frame.shape[1]
frame_height = frame.shape[0]
#### Passing the image to darknet
image, detections = image_detection(image_path, network, class_names, class_colors, thresh=0.05)
#cv2.imwrite(f'/home/ubuntu/temp/Inference{frame_number}.jpg', image)
#cv2.imwrite(f'/home/ubuntu/temp/orignal_detect{frame_number}.jpg', frame)
###Based on the detections, running them through a loop to draw bounding box and also incrememnt count of object in the frame
#4. Calculate count and draw bounding boxes
for i in range(len(detections)):
xc_percent = detections[i][2][0]/dn_frame_width
yc_percent = detections[i][2][1]/dn_frame_height
w_percent = detections[i][2][2]/dn_frame_width
h_percent = detections[i][2][3]/dn_frame_height
xc = xc_percent*frame_width
yc = yc_percent*frame_height
w = w_percent*frame_width
h = h_percent*frame_height
xmin = xc - w/2.0
ymin = yc - h/2.0
xmax = xc + w/2.0
ymax = yc + h/2.0
#If object is detected, increase the count of the object in the frame
if detections[i][0] == "bottle":
cv2.rectangle(frame, (int(xmin),int(ymin)),(int(xmax),int(ymax)),(0,0,255),2)
cv2.putText(frame, "bottle", (int(xmin), int(ymin-10)), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,255), 2)
quantity_frame += 1
elif detections[i][0] == "can":
cv2.rectangle(frame, (int(xmin),int(ymin)),(int(xmax),int(ymax)),(255,0,0),2)
cv2.putText(frame, "can", (int(xmin), int(ymin-10)), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,0,0), 2)
else:
print(f"{image} has no objects ")
print(f"Quantity in frame {frame_number} = {quantity_frame}")
#5. Store these images in respective directoies
cv2.imwrite(output_path, frame)
quantity_bottles_frame.append(quantity_frame)
frame_number += 1
###Split the points into equidistant points between start point and end point
##6. Take start point of lane and end point and split into many coordinates in between based on number of frames
distance, bearing_deg = get_distance_bearing(start_point_list[j-1][0], start_point_list[j-1][1], end_point_list[j-1][0], end_point_list[j-1][1])
print(distance)
lat_array, lon_array = discretize_line(start_point_list[j-1][0], start_point_list[j-1][1], float(d_element[0]), distance, bearing_deg)
lat_csv = []
lon_csv = []
##Convery those points into degrees
for lat,lon in zip(lat_array, lon_array):
lat_degrees = "{:}".format(np.degrees(lat))
lon_degrees = "{:}".format(np.degrees(lon))
lat_csv.append(lat_degrees)
lon_csv.append(lon_degrees)
#lat_csv = "{:}".format(np.degrees(lat))
#lon_csv = "{:}".format(np.degrees(lon))
##7.Write each row in the csv file
for k in range(d_element[0]):
dataCSVWriter.writerow([lat_csv[k], lon_csv[k], quantity_bottles_frame[k]])
#if k != d_element[0]-1:
# dataCSVWriter.writerow([lat_csv[k], lon_csv[k], quantity_bottles_frame[k], "-", "-" ])
if k ==d_element[0]-1:
print(lat_csv[int(d_element[0]/2)])
thumbnail_dataCSVWriter.writerow([ lat_csv[int(d_element[0]/2)],lon_csv[int(d_element[0]/2)]])
#####8.STACKING THE IMAGES ######
images = []
stacking_input = f"/home/ubuntu/pano/lane{j}/*.jpg"
list_images = glob.glob(stacking_input)
#print(list_images)
stacking_input_reverse = sorted(list_images, reverse = True)
print(stacking_input_reverse)
for image in stacking_input_reverse:
img = cv2.imread(image)
images.append(img)
final_image = cv2.hconcat(images)
image_name = f"cloud_lane{j}_stack.jpg"
stacking_output = f"/home/ubuntu/pano/stack"
output_path = os.path.join(stacking_output, image_name)
cv2.imwrite(output_path, final_image)
##### 9. DELETE FRAMES AFTER ONE ITERATION OF LOOP #####
for f in os.listdir(image_dir):
del_path = "/home/ubuntu/pano/Frames/" + f
os.remove(del_path)
else:
continue
#Close csv file
#data_file.close()
#thumbnail_data_file.close()
### 10. Upload to s3 bucket ####
stack_path = "/home/ubuntu/pano/stack"
for file in sorted(os.listdir(stack_path)):
print(f"Uploading {file}")
uploaded = upload_to_aws(f'/home/ubuntu/pano/stack/{file}', 'fbt-pano-test', f'{file}')
Do i need to close the csv file in any way? Or does s3 not support csv upload through boto3?
I found it. Turns out, the csv files werent closed at the end. So i moved the upload to s3 part to another program. now python closes the csv files at the end of this program automatically. and so when the upload program runs next, it gets uploaded properly.
Related
How can I make cluster of near similar images in dictionary based on imageHash without repeating same images in Dictionary
So i have a folder with images I am trying to make cluster of near similar images in a python dictionary with Imagehash as the key and a list of similar images as their value, how can i prevent for a image to generate a new key if it's already present in any of the other dictionary key list here is the code that I have done so far: from PIL import Image import imagehash import cv2 import numpy as np import dhash import distance norm_cache: dict = dict() def _get_image(image_path: str) -> Image: try: img_arr = cv2.imread(image_path) img_arr = cv2.resize(img_arr, (512, 512), interpolation=cv2.INTER_AREA) # Convert image into 3 channels if it contains 4 if len(img_arr.shape) > 2 and img_arr.shape[2] == 4: img_arr = cv2.cvtColor(img_arr, cv2.COLOR_BGRA2BGR) # using W3C luminance calc to convert into gray-scale data = np.inner(img_arr, [299, 587, 114]) / 1000.0 return Image.fromarray(np.uint8(data),"L") except SyntaxError: pass def find_similar_images(userpath): import os global norm_cache def is_image(filename): f = filename.lower() return f.endswith(".png") or f.endswith(".jpg") or \ f.endswith(".jpeg") or f.endswith(".bmp") or f.endswith(".gif") image_filenames = [os.path.join(userpath, path) for path in os.listdir(userpath) if is_image(path)] images = {} buffer = [] for img in image_filenames: if (len(buffer) == 0): print("Original list is empty, Appending first image to buffer.") buffer.append(img) continue gray1 = _get_image(img) h1r,h1c = dhash.dhash_row_col(gray1) hash1 = dhash.format_hex(h1r,h1c) images[hash1] = images.get(hash1, []) + [img] for each in buffer: if each in norm_cache: print(f"cached val found for {each}") gray2 = norm_cache[each] h2r,h2c = dhash.dhash_row_col(gray2) hash2 = dhash.format_hex(h2r,h2c) else: print("No cached_val found, Computing and storing in norm_cache") gray2 = _get_image(each) h2r,h2c = dhash.dhash_row_col(gray2) hash2 = dhash.format_hex(h2r,h2c) norm_cache[each] = gray2 # Update cache... print(f"Comparing ---> {img}:{hash1} with {each}:{hash2}") if(distance.hamming(hash1,hash2) <= 22): //what should i put in here unique = 0 for k, img_list in images.items(): if(len(img_list) >= 1): print(''.join(img_list)) unique = unique + 1 print(unique) if __name__ == '__main__': import sys, os userpath = <Image folder/> find_similar_images(userpath=userpath)
Set Author, Title, and Subject for PDF using Reportlab
How can you correctly set the Author, Title and Subject attributes for a PDF File using Reportlab? I have found the methods in the Reportlab User Guide on page 56, but I am not sure how to implement them correctly. Below in my PDF cropping and scaling script, I have added the annotations method, but I don't know where to call them from, or if a whole new Canvas object is needed. Please excuse the lengthy code, but only after line 113 is the doc being created, above are mostly auxiliary methods, including the annotations method on line 30. # All the necessary parameters are accessible after line 92, # but can of course be changed manually in the Code # imports for the crop, rename to avoid conflict with reportlab Image import from PIL import Image as imgPIL from PIL import ImageChops, ImageOps, ImageFilter import os.path, sys # import for the PDF creation import glob from reportlab.lib.pagesizes import A4 from reportlab.lib import utils from reportlab.platypus import Image, SimpleDocTemplate, Spacer from reportlab.pdfgen import canvas # get os path for Cropping path = (os.path.dirname(os.path.abspath("cropPDF.py"))) dirs = os.listdir(path) def trim(im, border="white"): bg = imgPIL.new(im.mode, im.size, border) diff = ImageChops.difference(im, bg) bbox = diff.getbbox() if bbox: return im.crop(bbox) def annotations(canvas): canvas.setAuthor("the ReportLab Team") canvas.setTitle("ReportLab PDF Generation User Guide") canvas.setSubject("How to Generate PDF files using the ReportLab modules") def findMaxWidth(): maxWidth = 0 for item in dirs: try: fullpath = os.path.join(path, item) if os.path.isfile(fullpath): im = imgPIL.open(fullpath) maxWidth = max(maxWidth, im.size[0]) except: pass return maxWidth def padImages(docHeight): maxWidth = findMaxWidth() for item in dirs: try: fullpath = os.path.join(path, item) if os.path.isfile(fullpath): im = imgPIL.open(fullpath) f, e = os.path.splitext(fullpath) width, height = im.size # get the image dimensions, the height is needed for the blank image if not docHeight <= height: # to prevent oversized images from bein padded, such that they remain centered image = imgPIL.new('RGB', (maxWidth, height), (255, 255, 255)) # create a white image with the max width image.paste(im, (0, 0)) # paste the original image overtop the blank one, flush on the left side image.save(f + ".png", "PNG", quality=100) except: pass def crop(): for item in dirs: try: fullpath = os.path.join(path, item) if os.path.isfile(fullpath): im = imgPIL.open(fullpath) f, e = os.path.splitext(fullpath) imCrop = trim(im, "white") imCrop.save(f + ".png", "PNG", quality=100) except: pass def add_page_number(canvas, doc): canvas.saveState() canvas.setFont('Times-Roman', numberFontSize) page_number_text = "%d" % (doc.page) canvas.drawCentredString( pageNumberSpacing * mm, pageNumberSpacing * mm, page_number_text ) canvas.restoreState() ############################# executeCrop = True executePad = True outputName = "output.pdf" #The name of the file that will be created fileAuthor = "Roman Stadler" #these 3 attributes are visible in the file info menu fileTitle = "" fileSubject = "" margin = 0.5 imageWidthDefault = 550 spacerHeight = 7 scalingIfImageTooTall = 0.95 # larger than 95 can result in an empty page after the image includePagenumbers = True numberFontSize = 10 pageNumberSpacing = 5 ############################ doc = SimpleDocTemplate( outputName, topMargin=margin * mm, leftMargin=margin * mm, rightMargin=margin * mm, bottomMargin=margin * mm, pagesize=A4 ) if executeCrop: crop() if executePad: padImages(doc.height) filelist = glob.glob("*.png") # Get a list of files in the current directory filelist.sort() story = [] # create the list of images for the PDF for fn in filelist: img = utils.ImageReader(fn) img_width, img_height = img.getSize() # necessary for the aspect ratio aspect = img_height / float(img_width) documentHeight = doc.height imageWidth = imageWidthDefault imageHeight = imageWidth * aspect if imageHeight > documentHeight: imageHeight = documentHeight * scalingIfImageTooTall imageWidth = imageHeight / aspect img = Image( fn, width=imageWidth, height=imageHeight ) story.append(img) space = Spacer(width=0, height=spacerHeight) story.append(space) if includePagenumbers and not len(filelist) == 0: # if pagenumbers are desired, or not doc.build( story, onFirstPage=add_page_number, onLaterPages=add_page_number, ) elif not len(filelist) == 0: doc.build(story) else: # to prevent an empty PDF that can't be opened print("no files found")
In the meantime, I have found another way, that does not use reportlab, but instead relies on PyPDF2: The following import is needed: # PyPDF2 for the metadata modification from PyPDF2 import PdfFileReader, PdfFileWriter Then the metadata can be edited like this: author = "Roman Stadler" title = "CropPDF" subject = "Stackoverflow" #rest of the script #attemp the metadate edit try: file = open('output.pdf', 'rb+') reader = PdfFileReader(file) writer = PdfFileWriter() writer.appendPagesFromReader(reader) metadata = reader.getDocumentInfo() writer.addMetadata(metadata) writer.addMetadata({ '/Author': author, '/Title': title, '/Subject' : subject, '/Producer' : "CropPDF", '/Creator' : "CropPDF", }) writer.write(file) file.close() except: print("Error while editing metadata")
You can define attributes like the author when defining the doc as a SimpleDocTemplate doc = SimpleDocTemplate( outputName, topMargin=margin * mm, leftMargin=margin * mm, rightMargin=margin * mm, bottomMargin=margin * mm, pagesize=A4, title="This is the title of the document", #exchange with your title author="John Smith", #exchange with your authors name subject"Adding metadata to pdf via reportlab" #exchange with your subject )
Merging and saving images in PIL Python
I have two folders of images and I am trying to build one large image from all the slices in each folder. I need to alternate between folders to build the image. For example the first slice comes from folder 1, the second slice comes from folder 2, the third from folder 1 ect. I have the files ordered by filename in the individual folders so I am trying to iterate through the folders and add a new strip to an image. The code runs BUT it doesn't seem to be saving the composite image. I am new to PIL, so I am sure that it is something simple, but your help is appreciated. Thanks! def merge_images(file1, file2): """Merge two images into one, displayed above and below :param file1: path to first image file :param file2: path to second image file :return: the merged Image object """ if file1.startswith('.'): return None image1 = Image.open(file1) image2 = Image.open(file2) (width1, height1) = image1.size (width2, height2) = image2.size result_width = width1 + width2 result_height = max(height1, height2) result = Image.new('RGB', (result_width, result_height)) result.paste(im=image1, box=(0, 0)) result.paste(im=image2, box=(0, height1)) return result imageCounter = 0 firstPass = True compImage = Image.new('RGBA', img.size, (0,0,0,0)) for i in range(len(boundingBoxes)+1): if firstPass: compImage = merge_images('./image_processing/'+ os.listdir('./image_processing/')[imageCounter], './img_patches/outputs/'+os.listdir('./img_patches/outputs/')[imageCounter]) if compImage is not None: firstPass = False compImage.save('./image_processing/compImage.jpg') else: compImage = merge_images('./image_processing/compImage.jpg','./image_processing/'+ os.listdir('./image_processing/')[imageCounter]) compImage.save('./image_processing/compImage.jpg') compImage = merge_images('./image_processing/compImage.jpg','./img_patches/outputs/'+ os.listdir('./img_patches/outputs/')[imageCounter]) compImage.save('./image_processing/compImage.jpg') imageCounter = imageCounter + 1
You have to tell PIL to save the images: for i in range(len(boundingBoxes)+1): if firstPass: compImage = merge_images('./image_processing/'+ os.listdir('./image_processing/')[imageCounter], './img_patches/outputs/'+os.listdir('./img_patches/outputs/')[imageCounter]) compImage.save(open('output/{}.png'.format(imageCounter), 'w'))
stitch images together in python
I am trying to stitch about 50 images(all in the same 287x287 size) together. Specifically, there should be 25 images on the top row and 25 images on the bottom row, and there also exists a small distance between each two images. I met two difficulties during my attempts: First problem is that there are 25 images in a folder with their name 'prefix-70',...,'prefix-94' while other 25 images in another folder with the same name 'prefix-70',...,'prefix-94'. I do not know how to them in Python without conflicts. Second problem is that I wrote the following code to read one folder images to form a row but it outputs a column. #!/usr/bin/python3.0 #encoding=utf-8 import numpy as np from PIL import Image import glob,os if __name__=='__main__': #prefix=input('Input the prefix of images:') prefix = 'prefix' files=glob.glob(prefix+'-*') num=len(files) filename_lens=[len(x) for x in files] #length of the files min_len=min(filename_lens) #minimal length of filenames max_len=max(filename_lens) #maximal length of filenames if min_len==max_len:#the last number of each filename has the same length files=sorted(files) #sort the files in ascending order else: index=[0 for x in range(num)] for i in range(num): filename=files[i] start=filename.rfind('-')+1 end=filename.rfind('.') file_no=int(filename[start:end]) index[i]=file_no index=sorted(index) files=[prefix+'-'+str(x)+'.png' for x in index] print(files[0]) baseimg=Image.open(files[0]) sz=baseimg.size basemat=np.atleast_2d(baseimg) for i in range(1,num): file=files[i] im=Image.open(file) im=im.resize(sz,Image.ANTIALIAS) mat=np.atleast_2d(im) print(file) basemat=np.append(basemat,mat,axis=0) final_img=Image.fromarray(basemat) final_img.save('merged.png') I guess i have got into a wrong way... How can i stitch them properly? Any suggestion is appreciated.
Try this (explanation in comments): from PIL import Image from os import listdir, path space_between_row = 10 new_image_path = 'result.jpg' im_dirs = ['images/1', 'images/2'] # get sorted list of images im_path_list = [[path.join(p, f) for f in sorted(listdir(p))] for p in im_dirs] # open images and calculate total widths and heights im_list = [] total_width = 0 total_height = 0 for path_list in im_path_list: images = list(map(Image.open, path_list)) widths, heights = zip(*(i.size for i in images)) total_width = max(total_width, sum(widths)) total_height += max(heights) im_list.append(images) # concat images new_im = Image.new('RGB', (total_width, total_height)) y_offset = 0 for images in im_list: x_offset = 0 max_height = 0 for im in images: new_im.paste(im, (x_offset, y_offset)) x_offset += im.size[0] max_height = max(im.size[1], max_height) y_offset = y_offset + max_height + space_between_row # show and save new_im.show() new_im.save(new_image_path)
Install ImageMagick, then tell it where your two directories are. #!/usr/bin/python3 ##========================================================= ## required ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## ## imagemagick.org/script/download.php ## ##========================================================= ## libs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import subprocess as sp ##========================================================= ## vars ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ offset = 2 ## pixel gap between images color = '#000000' ## background color to fill gaps dir1 = '/home/me/Pictures/topRow/' dir2 = '/home/me/Pictures/bottomRow/' ## note: windows dirs use double backslashes ## 'C:\\Users\\me\\Pictures\\topRow\\' ##========================================================= ## script ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ row1args = ['convert', '+smush', offset, '-background', color, dir1 + '*.png', 'row1.png'] row2args = ['convert', '+smush', offset, '-background', color, dir2 + '*.png', 'row2.png'] merge = ['convert', '-smush', offset, '-background', color, 'row*.png', 'merged.png'] ##========================================================= ## main ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sp .call(row1args) sp .call(row2args) sp .call(merge) ##========================================================= ## eof ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compare a single image with 10 or more images and find the matching one
when i run the program I need my code to : initialize the camera take a picture request user to enter paths for the current image to be stored and the image to be compared to detect edges of currently taken picture and save in database compare current edge image to 10 or more edge images in database output as the edge image that has highest match percentage with current edge image basically its like an object identification program ... can someone please help me out ? here is the code i have done so far from itertools import izip import numpy as np import cv2 from matplotlib import pyplot as plt from PIL import Image def take_and_save_picture(im_save): '''Take a picture and save it Args: im_save: filepath where the image should be stored ''' camera_port = 0 ramp_frames = 30 cap = cv2.VideoCapture(camera_port) def get_image(): retval, im = cap.read() return im for i in xrange(ramp_frames): temp = get_image() print("Taking image...") # Take the actual image we want to keep camera_capture = get_image() #im_save_tmp = im_save + '.jpg' im_save_tmp = im_save # A nice feature of the imwrite method is that it will automatically choose the # correct format based on the file extension you provide. Convenient! cv2.imwrite(im_save_tmp, camera_capture) # You'll want to release the camera, otherwise you won't be able to create a new # capture object until your script exits # del(cap) img1 = cv2.imread(im_save_tmp, 0) edges = cv2.Canny(img1, 100, 200) cv2.imwrite(im_save, edges) cv2.waitKey(0) cv2.destroyAllWindows() #im1 = "/Users/Me/gop.jpg" #im2 = "/Users/Me/aarthi.jpg" im1 = input('enter the path of database file') im2 = input('enter the path where captured image is to be saved') #im1="/Users/Me/home1.png" #im2="/Users/Me/home.png" def compute_edges_diff(im1, im2): '''Compute edges diff between to image files. Args: im1: filepath to the first image im2: filepath to the second image Returns: float: percentage of difference between images ''' #for no_file1 in range(0,10): #template = cv2.imread('numbers1/{no_file}.png'.format(no_file=no_file1),0) i1 = Image.open(im1) i2 = Image.open(im2) assert i1.mode == i2.mode, "Different kinds of images." assert i1.size == i2.size, "Different sizes." pairs = izip(i1.getdata(), i2.getdata()) if len(i1.getbands()) == 1: # for gray-scale jpegs dif = sum(abs(p1-p2) for p1,p2 in pairs) else: dif = sum(abs(c1-c2) for p1,p2 in pairs for c1,c2 in zip(p1,p2)) ncomponents = i1.size[0] * i1.size[1] * 3 diff = (dif / 255.0 * 100) / ncomponents return diff def main(): #capture_img = "/Users/Me/home1.png" capture_img = input('enter path of the file from database') #img_to_compare = "/Users/Me/Documents/python programs/compare/img2.jpg" take_and_save_picture(capture_img) diff = compute_edges_diff(im1, im2) print "Difference (percentage):", diff if diff > 0.5: print im1 else : print im2 if __name__ == '__main__': main() #del(cap) this code works fine .. but i am able to compare only one image ... i need to compare the current taken images with all images in my database ...
In your main function, create a list to ask for the path for the image files, wrap the compare in a for loop: def get_images_to_compare(): images_to_compare = [] while True: comp_img = raw_input("Path of image to compare to: ") if len(comp_img) <= 1: # break if someone just hits enter break images_to_compare.append(comp_img) return images_to_compare def main(): #capture_img = "/Users/Me/home1.png" capture_img = input('enter path of the file from database') #img_to_compare = "/Users/Me/Documents/python programs/compare/img2.jpg" take_and_save_picture(capture_img) #### you have some odd var names here, basic gist, add a for loop for comp_image in get_images_to_compare(): diff = compute_edges_diff(im1, im2) print "Difference (percentage):", diff if diff > 0.5: print im1 else: print im2 as a suggestion, avoid having global scope vars intermingled between functions, it makes code hard to read (referring to you setting im1 and im2 between two fn defs. Code for doing the multiple compares: def main(folder_path_to_search, files_to_compare_to, source_image_path): #capture_img = "/Users/Me/home1.png" capture_img = input('enter path of the file from database') #img_to_compare = "/Users/Me/Documents/python programs/compare/img2.jpg" take_and_save_picture(capture_img) images_to_compare = [ os.path.join(folder_path_to_search,file_path) for file_path in os.listdir(folder_path_to_search) if file_path.endswith(files_to_compare_to) ] for comp_image in get_images_to_compare(): diff = compute_edges_diff(source_image_path, comp_image) print "Difference (percentage):", diff, "(", source_image_path, ":", comp_image, ")" if __name__ == '__main__': folder_path_to_search = raw_input("Enter folder path to search") files_to_compare_to = raw_input("enter file extention to glob ex: '.jpg'") source_image_path = raw_input("enter full file path of source image") main(folder_path_to_search, files_to_compare_to, source_image_path)