How to batch combine 2 photos into 1 in python - merge

I'm trying to find a way to batch combine multiple pairs of images into a single image horizontally. I have a folder of hundreds of photos (img01, img02,etc) and I'm trying to merge pairs of these:
img1 + img2 --> img1_2
img 519 + img 520 --> img519_520
The images are 3 x 4 inches and I want to combine them into pairs of horizontal 6 x 4 inch images.
I have found a way to do this for 2 specific photos but I don't know how to loop the code for all the photos in my image folder and save this as a 6x4 photo.
import numpy as np
from PIL import Image
images_list = ['img52.JPG', 'img53.JPG']
imgs = [ Image.open(i) for i in images_list ]
min_img_shape = sorted( [(np.sum(i.size), i.size ) for i in imgs])[0][1]
img_merge = np.hstack( (np.asarray( i.resize(min_img_shape,Image.ANTIALIAS) ) for i in imgs )
img_merge = Image.fromarray( img_merge)
img_merge.save( 'Merged image.jpg' )
I am using a Mac OS High Sierra 10.13.4 and python Python 3.6.4.
Any help would be really appreciated!
Source of the above code: https://kanoki.org/2017/07/12/merge-images-with-python/

Update (as of 12 April 2018):
The following should work for a folder with an even number of photos, where the photos are named: img1.jpg, img2.jpg, etc. The script will take a pair of photos (e.g. img1.jpg and img2.jpg) and combine them.
#Note: I run the program in terminal after I change directory to my folder.
import numpy as np
from PIL import Image
images_list = []
for i in range(1,78): #insert last number of photo + 1 (in this case, I have 77 photos)
images_list.append('img'+str(i)+'.JPG')
count = 1;
directory = "path of directory" #change to directory where your photos are
ext = ".jpg"
new_file_name = "vimage-" #change to what you would like to name your photos
new_directory = "path of directory" # change to path of new directory where you want your photos to be saved
for j in range(0,len(images_list),2):
name = new_file_name + str(j) + ext
two_images_list = [images_list[j],images_list[j+1]]
imgs = [ Image.open(i) for i in two_images_list ]
min_img_shape = sorted( [(np.sum(i.size), i.size ) for i in imgs])[0][1]
imgs_comb = np.hstack( (np.asarray( i.resize(min_img_shape) ) for i in imgs ) )
imgs_comb = Image.fromarray( imgs_comb)
imgs_comb.save(new_directory+'/'+name )
count +=1
Thanks a lot to #C. Tim for the helpful response!

Update (as of 12 April 2018):
If your images have a name as "img01.JPG", "img42.JPG", this code should work :
you generate all the names and put them in a list. For each pair of images your algorithm converts them into one image and the name of the images created change for every pair.
You must have an even number of images and the images need to be of the same dimension. Thanks a lot to #C. Tim for the helpful response.
# Note: I run the program in terminal after I change directory to my folder.
import numpy as np
from PIL import Image
images_list = []
for i in range(1,78): #insert last number of photo
images_list.append('img'+str(i)+'.JPG')
count = 1;
directory = "path of photos to resize" #change to directory where your photos are
ext = ".jpg"
new_file_name = "vimage-"
new_directory = "path to save in" # change to path of new directory where you want your photos to be saved
for j in range(0,len(images_list),2):
name = new_file_name + str(j) + ext
two_images_list = [images_list[j],images_list[j+1]]
imgs = [ Image.open(i) for i in two_images_list ]
min_img_shape = sorted( [(np.sum(i.size), i.size ) for i in imgs])[0][1]
imgs_comb = np.hstack( (np.asarray( i.resize(min_img_shape) ) for i in imgs ) )
imgs_comb = Image.fromarray( imgs_comb)
imgs_comb.save(new_directory+'/'+name )
count +=1

Related

Macro for multiple images analysis in the calculator plus

I have a set of images in a folder which their names are: 2 days.bmp 3 days.bmp ..... 28 days.bmp. Also, I have a folder with the background images exactly with the same names. I want to use the calculator plus and divide each image to its relevant background. I want to save time and do that at the same time instead of doing it for each image one by one. Is there any idea how can I do that? I have written a macro but it didn't work for me.
macro "Batch calculate images [1]" {
LocationOfFiles = getDirectory("Select Folder");
LocationOfbackgrounds = getDirectory("Select Folder of backgrounds");
LocationOfSave = getDirectory("Select Save Location");
setBatchMode(true);
FileList = getFileList(LocationOfFiles);
NumberOfFiles = FileList.length;
for (i=0; i<NumberOfFiles; i+=1) {
FileName = FileList[i];
pathtofile1 = LocationOfFiles+FileName;
open(pathtofile1);
name1 = getTitle();
pathtofile2 = LocationOfbackgrounds+FileName;
open(pathtofile2);
name2 = getTitle();
run("Calculator Plus", "i1="+name1+" i2="+name2+" operation=[Divide: i2 = (i1/i2) x k1 + k2] k1=255 k2=0 create");
selectWindow("Result");
SaveName = replace(name, ".bmp", "_backgroud subtracted.jpg");
saveAs("BMP", LocationOfSave+SaveName);
selectWindow(BackgroundImage);
close("\\Others");

find correlation images in folders and print result in excel using matlab

I tried to compare my template image ( image2 ) with image folders names as test* ( test1 , test 2 .... test n) to find correlation between my template image with images from that folder , then print result in that folder then go to next folder test2 .. till test n , thats mean the result of find correlation with each image in folder test1 its print as excel file named ( any name ) store in folder test1 and the content of that excel file as follow :
first row contain the names of images in folder test1 ,
second row contain the correlation result if 0 or 1 after that its jump to next folder test2 ...test3.... etc
the following code i tried long time
xls_sheet = 'Sheet1';
column_range = 'B'; % Initialisation of the column range
srcFolders = dir('D:\test*');
xls_filename = 'result.xls';
for folder = 1:length(srcFolders)
path = strcat('D:\',srcFolders(folder).name);
xlswrite('D:\srcFiles(i)\xls_filename',{srcFolders(folder).name},xls_sheet,folder_range); %Writing the name of the folder in the first row
sear = strcat(path, '\*.bmp');
srcFiles = dir(sear);
row_range = '2';
srcFolders = dir('D:\');
for folder = 1:length(srcFolders)
srcFolders(folder).fullname = strcat('image:\',srcFolders(folder).name);
end
xlswrite('D:\xlsFile', {srcFolders(:).fullname}, 'Sheet1','A2');
for i = 1 : length(srcFiles)
filename = strcat(path,'\',srcFiles(i).name);
Image1= imread(filename);
Image2 = imread('D:\act','jpeg');
x = corr2(Image1,Image2);
file_range = strcat(column_range, row_range);
if (x = 0)
xlswrite(xls_filename, {'0'}, xls_sheet, file_range ); %Writing '0' in the second row
else
xlswrite(xls_filename, {'1'}, xls_sheet, file_range ); %Writing '1' in the second row
end
end
row_range = char(row_range + 1); %Moving to the next row
column_range = char(column_range + 1); %Moving to the next column
end
i print names of files in first row , and
my questions how :
1- we can print excel file in each test* folders .
2- how can i repeat this process for all test* folders .
in the result i hope to get excel file in each and every folder in test1 , test 2 ... that contain 1 for corr=1 and 0 for others for all images in that folder.

Renaming files in mass in MATLAB

When collecting data, I've currently named my files in the following format:
1_10.mat
Where the number before the underscore is a continent:
1- Africa
2- South America
3- Central America
The second number is the day in that continent the measurement was made on. What I'd like to do is to add the country the measurements were made in onto the end of the filename as well. For example:
1_1 --> 1_10 I want to rename each one to 1_1_Zaire --> 1_10_Zaire
1_11 --> 1_14, I want to rename each one to 1_11_Kenya --> 1_11_Kenya
How could I do this while keeping all the .mat files in the same folder? I'd prefer to use MATLAB for the renaming if possible.
I understand the algorithm will be something like the following:
name a directory with all the .mat files
make a for loop from bound 1 to bound x
concatenate the phrase I want
The only problem is, I don't know how to get the length of the loop, and I don't understand how MATLAB reads files in a directory.
This is what I've tried.
directory = 'C:\place';
for 1 : 9
curName = directory.name;
s = '_Africa';
laterName = (strcat(directory,s)).name;
end
Something like this should get you started:
directory = 'C:\place\';
% Filter the list of files using * as a wildcard.
file = strcat(directory, '*.mat');
% Get a list of files and concatenate them with the directory name.
results = dir(file);
file_name = strcat(directory, '\', num2cell(char(results.name), 2)')';
% The total number of files
nfile = length(file_name)
% Loop through each file.
for i = 1: nfile
curName = file_name{i}
d = textscan(curName, '%3s%f%1s%f');
if (d{2} == 1)
if (1 <= d{4} && d{4} <= 10)
laterName = sprintf('.\\%i_%i_Zaire.mat', d{2}, d{4})
elseif (11 <= d{4} && d{4} <= 14)
laterName = sprintf('.\\%i_%i_Kenya.mat', d{2}, d{4})
end
else
% ...
end
end

Read with order files in subfolders in matlab

I've got a folder which contains subfolders with text files. I want to read those file with the same order as they are in the subfolders. I've got a problem with that. I use the following matlab code:
outNames = {};
k=1;
feature = zeros(619,85);
fileN = cell(619,1);
for i=1:length(nameFolds)
dirList = dir(strcat(path, num2str(cell2mat(nameFolds(i,1)))));
names = {dirList.name};
outNames = {};
for j=1:numel(names)
name = names{j};
if ~isequal(name,'.') && ~isequal(name,'..')
[~,name] = fileparts(names{j});
outNames{end+1} = name;
fileName = strcat(path, num2str(cell2mat(nameFolds(i,1))), '\', name, '.descr' );
feature(k,:) = textread(fileName);
fileN{k} = [fileName num2str(k)];
k= k+1;
end
end
end
In one subfolder I've got the above text file names:
AnimalPrint_tiger_test_01.descr
AnimalPrint_tiger_test_02.descr
AnimalPrint_tiger_test_03.descr
AnimalPrint_tiger_test_04.descr
AnimalPrint_tiger_test_05.descr
AnimalPrint_tiger_test_06.descr
AnimalPrint_tiger_test_07.descr
AnimalPrint_tiger_test_08.descr
AnimalPrint_tiger_test_09.descr
AnimalPrint_tiger_test_10.descr
AnimalPrint_tiger_test_11.descr
AnimalPrint_tiger_test_12.descr
AnimalPrint_tiger_test_13.descr
AnimalPrint_tiger_test_14.descr
AnimalPrint_tiger_test_15.descr
AnimalPrint_zebra_test_1.descr
AnimalPrint_zebra_test_2.descr
AnimalPrint_zebra_test_3.descr
AnimalPrint_zebra_test_4.descr
AnimalPrint_zebra_test_5.descr
AnimalPrint_zebra_test_12.descr
But it seems that it reads first the AnimalPrint_zebra_test_12.descr and after the AnimalPrint_zebra_test_1.descr and the rest. Any idea why this happens?
dir sorts the files according to their names, for instance
test_1
test_12 % 1 followed by 2
test_2
test_3
You may want to build your own order with ['test_' num2str(variable) '.descr'] that concatenates test_ with an incrementing variable.

how to determine the transparent color index of ICO image with PIL?

Specifically, this is from an .ico file, so there is no "transparent" "info" attribute like you would get in a gif. The below example illustrates converting Yahoo!'s favicon to a png using the correct transparency index of "0", which I guessed. how to detect that the ico is in fact transparent and that the transparency index is 0 ?
import urllib2
import Image
import StringIO
resp = urllib2.urlopen("http://www.yahoo.com/favicon.ico")
image = Image.open(StringIO.StringIO(resp.read()))
f = file("test.png", "w")
# I guessed that the transparent index is 0. how to
# determine it correctly ?
image.save(f, "PNG", quality=95, transparency=0)
looks like someone recognized that PIL doesn't really read ICO correctly (I can see the same thing after reconciling its source code with some research on the ICO format - there is an AND bitmap which determines transparency)
and came up with this extension:
http://www.djangosnippets.org/snippets/1287/
since this is useful for non-django applications, I've reposted here with a few tweaks to its exception throws:
import operator
import struct
from PIL import BmpImagePlugin, PngImagePlugin, Image
def load_icon(file, index=None):
'''
Load Windows ICO image.
See http://en.wikipedia.org/w/index.php?oldid=264332061 for file format
description.
'''
if isinstance(file, basestring):
file = open(file, 'rb')
try:
header = struct.unpack('<3H', file.read(6))
except:
raise IOError('Not an ICO file')
# Check magic
if header[:2] != (0, 1):
raise IOError('Not an ICO file')
# Collect icon directories
directories = []
for i in xrange(header[2]):
directory = list(struct.unpack('<4B2H2I', file.read(16)))
for j in xrange(3):
if not directory[j]:
directory[j] = 256
directories.append(directory)
if index is None:
# Select best icon
directory = max(directories, key=operator.itemgetter(slice(0, 3)))
else:
directory = directories[index]
# Seek to the bitmap data
file.seek(directory[7])
prefix = file.read(16)
file.seek(-16, 1)
if PngImagePlugin._accept(prefix):
# Windows Vista icon with PNG inside
image = PngImagePlugin.PngImageFile(file)
else:
# Load XOR bitmap
image = BmpImagePlugin.DibImageFile(file)
if image.mode == 'RGBA':
# Windows XP 32-bit color depth icon without AND bitmap
pass
else:
# Patch up the bitmap height
image.size = image.size[0], image.size[1] >> 1
d, e, o, a = image.tile[0]
image.tile[0] = d, (0, 0) + image.size, o, a
# Calculate AND bitmap dimensions. See
# http://en.wikipedia.org/w/index.php?oldid=264236948#Pixel_storage
# for description
offset = o + a[1] * image.size[1]
stride = ((image.size[0] + 31) >> 5) << 2
size = stride * image.size[1]
# Load AND bitmap
file.seek(offset)
string = file.read(size)
mask = Image.fromstring('1', image.size, string, 'raw',
('1;I', stride, -1))
image = image.convert('RGBA')
image.putalpha(mask)
return image