Commit d8cad196 authored by Jonathan Barés's avatar Jonathan Barés
Browse files

First working version of the different codes. A TODO list is also added.

parents
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/track_root.iml" filepath="$PROJECT_DIR$/.idea/track_root.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TestRunnerService">
<option name="projectConfiguration" value="pytest" />
<option name="PROJECT_TEST_RUNNER" value="pytest" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Load libraries:
import numpy as np
import os
import glob
import time
import datetime
from PIL import Image
from scipy import misc
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from multiprocessing import Pool
from matplotlib.widgets import RectangleSelector
#Input parameter:
##Number of processor for post-processing parallelization:
NbProc=4
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Rename file and create time vectors:
print('... is sorting pictures')
##Get picutre names:
nam_pict=glob.glob('picture/*.jpg')
##Count the number of pictures in the folder to get the number of kept steps:
NbStp=len(nam_pict)
##Initialise time vector:
timePic=np.zeros(NbStp)
##Create picture vector:
null=os.system('mkdir pictureWh')
##Loop over picture to get their times:
for it in range(len(nam_pict)):
tmp=Image.open(nam_pict[it])._getexif()[36867]
dt_tmp=datetime.datetime.strptime(tmp, '%Y:%m:%d %H:%M:%S')
timePic[it]=time.mktime(dt_tmp.timetuple())
##Sort time vector convert in min and save it:
timePic-=np.min(timePic)
Is=np.argsort(timePic)
timePic=timePic[Is]
timePic/=60.
np.savetxt('time.txt',timePic,delimiter='\n')
##Loop over picture to sort and rename them:
for it in range(len(nam_pict)):
os.system('cp '+nam_pict[Is[it]]+' pictureWh/'+str(it).zfill(4)+'.jpg')
##Remove picture folder:
os.system('rm -rf picture')
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Rotate pictures:
print('... is rotating pictures')
##Function to rotate pictures:
def RotatePicture(iPct):
print iPct
null=os.system('convert pictureWh/'+'%04d'%iPct+'.jpg -rotate 270 pictureWh/'+'%04d'%iPct+'.jpg')
return 0
##Parallelization of the rotation:
p=Pool(NbProc)
null=p.map(RotatePicture,xrange(NbStp))
p.close()
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Reframe pictures:
##Select the area of interest:
###Waiting:
print raw_input('Is waiting. Press ENTER to move...')
###Open the last picture:
pict1=mpimg.imread('pictureWh/'+'%04d'%(NbStp-1)+'.jpg')
###Define selection functions:
def line_select_callback(eclick,erelease):
global x1, y1, x2, y2
x1,y1=eclick.xdata,eclick.ydata
x2,y2=erelease.xdata,erelease.ydata
def toggle_selector(event):
print(' Key pressed.')
if event.key in ['Q', 'q'] and toggle_selector.RS.active:
print(' RectangleSelector deactivated.')
toggle_selector.RS.set_active(False)
if event.key in ['A', 'a'] and not toggle_selector.RS.active:
print(' RectangleSelector activated.')
toggle_selector.RS.set_active(True)
###Select:
fig,current_ax=plt.subplots()
plt.imshow(pict1,cmap=plt.cm.Greys)
plt.title('select area to consider, close to validate')
toggle_selector.RS=RectangleSelector(current_ax,line_select_callback,drawtype='box',useblit=True,button=[1,3],minspanx=5,minspany=5,spancoords='pixels',interactive=True)
plt.connect('key_press_event',toggle_selector)
plt.show()
plt.close()
##Function to crop the pictures:
def CropPicture(iPct):
global x1, y1, x2, y2
print iPct
###Load pictures:
pict1=misc.imread('pictureWh/'+'%04d'%iPct+'.jpg')
###Crop pictures:
pictF1=pict1[int(y1):int(y2),int(x1):int(x2),:]
###Save picture:
misc.imsave('pictureWh/'+'%04d'%iPct+'.jpg',pictF1)
##Parallelization of the cropping:
print('... is cropping pictures')
p=Pool(NbProc)
null=p.map(CropPicture,xrange(NbStp))
p.close()
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Create movies:
##Create picture vector:
null=os.system('mkdir tmpWh')
##function to plot the pictures with the time:
def PlotPicture(iPct):
global timePic
print iPct
###Load the time:
t0=timePic[iPct]
h0,m0=divmod(t0,60)
j0,h0=divmod(h0,24)
###Load pictures:
pict1=mpimg.imread('pictureWh/'+'%04d'%iPct+'.jpg')
###Plot picture:
plt.imshow(pict1)
plt.axis('off')
plt.title('%02d'%j0+'days '+'%02d'%h0+'hours - '+str(iPct))
plt.savefig('tmpWh/'+'%04d'%iPct+'.png',dpi=200)
plt.close()
##Parallelization of the cropping:
print('... is plotting pictures')
p=Pool(1)
null=p.map(PlotPicture,xrange(NbStp))
p.close()
##Make movies:
print('... is making the movie')
null=os.system('ffmpeg -r 15 -y -f image2 -i tmpWh/%04d.png -qscale 1 Wh.avi')
##Remove folders:
null=os.system('rm -f -R tmpWh')
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Load libraries:
import numpy as np
import os
import glob
import fnmatch
from scipy import misc
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from multiprocessing import Pool
#Input parameter:
##Initial and last image number:
Ni=1
Nl=965
##Number of processor for post-processing parallelization:
NbProc=5
#Define global variables:
global row, col, timePic
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Rename file and create time vectors:
print('... is sorting pictures')
##Count the number of pictures in the folder to get the number of keeped steps:
NbStp=len(fnmatch.filter(os.listdir('.'), '*.jpg'))/2
##Initialise time vector:
timePic=np.zeros(NbStp)
##Create picture vector:
null=os.system('mkdir picturePl')
null=os.system('mkdir pictureWh')
##Loop over picture names:
cnt=0
for it1 in xrange(Ni,Nl+1):
try:
###Find picture names:
namCurPl=glob.glob('%04d'%it1+'_*_Pl.jpg')[0]
namCurWh=glob.glob('%04d'%it1+'_*_Wh.jpg')[0]
###Extract time:
timePic[cnt]=int(namCurPl[namCurPl.index('_')+1:namCurPl.index('_')+(namCurPl[namCurPl.index('_')+1:-1]).index('_')+1])
###Rename pictures:
null=os.system('mv '+namCurPl+' picturePl/'+'%04d'%cnt+'.jpg')
null=os.system('mv '+namCurWh+' pictureWh/'+'%04d'%cnt+'.jpg')
###Increment:
cnt+=1
except:
print('Picture '+'%04d'%it1+' is missing')
##Save time vector:
timePic-=np.amin(timePic)
np.savetxt('time.txt',timePic,delimiter='\n')
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Rotate pictures:
print('... is rotating pictures')
##Function to rotate pictures:
def RotatePicture(iPct):
print iPct
null=os.system('convert picturePl/'+'%04d'%iPct+'.jpg -rotate 90 picturePl/'+'%04d'%iPct+'.jpg')
null=os.system('convert pictureWh/'+'%04d'%iPct+'.jpg -rotate 90 pictureWh/'+'%04d'%iPct+'.jpg')
return 0
##Parallelization of the rotation:
p=Pool(NbProc)
null=p.map(RotatePicture,xrange(NbStp))
p.close()
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Reframe pictures:
##Measure picture size:
pict1=misc.imread('picturePl/'+'%04d'%0+'.jpg')[:,:,1] #current
row,col=pict1.shape
##Function to measure the shift:
def MeasurePictureShift(iPct):
global row, col
print iPct
###Load pictures:
pict1=misc.imread('picturePl/'+'%04d'%iPct+'.jpg')[:,:,1]
pict2=misc.imread('picturePl/'+'%04d'%(iPct+1)+'.jpg')[:,:,1]
###Compute Fourier transform:
pict1FFT=np.fft.fft2(pict1)
pict2FFT=np.conjugate(np.fft.fft2(pict2))
###Convolute:
pictCCor=np.real(np.fft.ifft2((pict1FFT*pict2FFT)))
###Compute the shift:
pictCCorShift=np.fft.fftshift(pictCCor)
yShift,xShift=np.unravel_index(np.argmax(pictCCorShift),(row,col))
yShift=yShift-int(row/2)
xShift=xShift-int(col/2)
a=np.argmax(pictCCorShift)
###return the shifts:
return xShift, yShift, a
##Parallelization of the shift computation:
print('... is centering pictures (measure displacement)')
p=Pool(NbProc)
xShiftVec0,yShiftVec0,test0=zip(*p.map(MeasurePictureShift,xrange(NbStp-1)))
xShiftVec0=np.array(xShiftVec0); yShiftVec0=np.array(yShiftVec0); test0=np.array(test0)
p.close()
##Detect picture problems and fix it:
###Peak a threshold on image correlation if needed:
plt.plot(np.abs(test0-np.mean(test0)),'o',markersize=5)
plt.xlabel('step')
plt.ylabel('correlation')
plt.title('Select a maximum acceptable value')
X=plt.ginput(1,timeout=-1)
plt.close()
II1=np.hstack((np.where(np.abs(test0-np.mean(test0))>X[0][1])[0],10000000))
###Peak a threshold on image shift if needed:
plt.plot(np.abs(xShiftVec0),'o',markersize=5)
plt.xlabel('step')
plt.ylabel('image shift')
plt.title('Select a maximum acceptable value')
X=plt.ginput(1,timeout=-1)
plt.close()
II2=np.hstack((np.where(np.abs(xShiftVec0)>X[0][1])[0],10000000))
II=np.unique(np.hstack((II1,II2)))
###Solve problems if necessary:
if len(II)>1:
print('Problem with following pictures: '+str(II)[1:-2])
III=np.hstack((np.array([-1]),np.where(np.diff(II)>1)[0]))
for it_III in range(len(III)-1):
it_ref=II[III[it_III]+1]
I_mod=np.array(range(it_ref+1,II[III[it_III+1]]+1))
for it_mod in I_mod:
os.system('rm -rf pictureWh/'+'%04d'%it_mod+'.jpg')
os.system('cp pictureWh/'+'%04d'%it_ref+'.jpg pictureWh/'+'%04d'%it_mod+'.jpg')
os.system('rm -rf picturePl/'+'%04d'%it_mod+'.jpg')
os.system('cp picturePl/'+'%04d'%it_ref+'.jpg picturePl/'+'%04d'%it_mod+'.jpg')
for it_II in II[0:-1]:
A0=MeasurePictureShift(it_II)
xShiftVec0[it_II]=A0[0]
yShiftVec0[it_II]=A0[1]
test0[it_II]=A0[2]
##Add the shifts:
xShiftVec=np.zeros(NbStp)
yShiftVec=np.zeros(NbStp)
for it in xrange(1,NbStp):
xShiftVec[it]=xShiftVec[it-1]+xShiftVec0[it-1]
yShiftVec[it]=yShiftVec[it-1]+yShiftVec0[it-1]
##Computation of the new image size:
MaxSft=np.amax(xShiftVec)+1
MinSft=np.amin(xShiftVec)-1
colN=int(col-MaxSft+MinSft)
rowN=row
##Rescale vectors:
xShiftVecN=(MaxSft-xShiftVec).astype(int)
##Function to reframe the pictures:
def ReframePicture(iPct):
print iPct
###Load pictures:
pict0=misc.imread('picturePl/'+'%04d'%iPct+'.jpg')
pict1=misc.imread('pictureWh/'+'%04d'%iPct+'.jpg')
###Crop pictures:
pictF0=pict0[:,xShiftVecN[iPct]:xShiftVecN[iPct]+colN,:]
pictF1=pict1[:,xShiftVecN[iPct]:xShiftVecN[iPct]+colN,:]
###Save picture:
misc.imsave('picturePl/'+'%04d'%iPct+'.jpg',pictF0)
misc.imsave('pictureWh/'+'%04d'%iPct+'.jpg',pictF1)
##Parallelization of the cropping:
print('... is centering pictures (crop)')
p=Pool(NbProc)
null=p.map(ReframePicture,xrange(NbStp))
p.close()
##Select the area of interest:
###Waiting:
print raw_input('Is waiting. Press ENTER to move...')
###Open the last picture:
pict1=mpimg.imread('pictureWh/'+'%04d'%(NbStp-1)+'.jpg')
###Define selection functions:
def line_select_callback(eclick,erelease):
global x1, y1, x2, y2
x1,y1=eclick.xdata,eclick.ydata
x2,y2=erelease.xdata,erelease.ydata
def toggle_selector(event):
print(' Key pressed.')
if event.key in ['Q', 'q'] and toggle_selector.RS.active:
print(' RectangleSelector deactivated.')
toggle_selector.RS.set_active(False)
if event.key in ['A', 'a'] and not toggle_selector.RS.active:
print(' RectangleSelector activated.')
toggle_selector.RS.set_active(True)
###Select:
fig,current_ax=plt.subplots()
plt.imshow(pict1,cmap=plt.cm.Greys)
plt.title('select area to consider, close to validate')
toggle_selector.RS=RectangleSelector(current_ax,line_select_callback,drawtype='box',useblit=True,button=[1,3],minspanx=5,minspany=5,spancoords='pixels',interactive=True)
plt.connect('key_press_event',toggle_selector)
plt.show()
plt.close()
##Function to crop the pictures:
def CropPicture(iPct):
global x1, y1, x2, y2
print iPct
###Load pictures:
pict0=misc.imread('picturePl/'+'%04d'%iPct+'.jpg')
pict1=misc.imread('pictureWh/'+'%04d'%iPct+'.jpg')
###Crop pictures:
pictF0=pict0[int(y1):int(y2),int(x1):int(x2),:]
pictF1=pict1[int(y1):int(y2),int(x1):int(x2),:]
###Save picture:
misc.imsave('picturePl/'+'%04d'%iPct+'.jpg',pictF0)
misc.imsave('pictureWh/'+'%04d'%iPct+'.jpg',pictF1)
##Parallelization of the cropping:
print('... is cropping pictures')
p=Pool(NbProc)
null=p.map(CropPicture,xrange(NbStp))
p.close()
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Create movies:
##Create picture vector:
null=os.system('mkdir tmpPl')
null=os.system('mkdir tmpWh')
##function to plot the pictures with the time:
def PlotPicture(iPct):
global timePic
print iPct
###Load the time:
t0=timePic[iPct]
h0,m0=divmod(t0,60)
j0,h0=divmod(h0,24)
###Load pictures:
pict0=mpimg.imread('picturePl/'+'%04d'%iPct+'.jpg')
pict1=mpimg.imread('pictureWh/'+'%04d'%iPct+'.jpg')
###Plot picture:
plt.imshow(pict0)
plt.axis('off')
plt.title('%02d'%j0+'days '+'%02d'%h0+'hours - '+str(iPct))
plt.savefig('tmpPl/'+'%04d'%iPct+'.png',dpi=200)
plt.close()
plt.imshow(pict1)
plt.axis('off')
plt.title('%02d'%j0+'days '+'%02d'%h0+'hours - '+str(iPct))
plt.savefig('tmpWh/'+'%04d'%iPct+'.png',dpi=200)
plt.close()
##Parallelization of the cropping:
print('... is plotting pictures')
p=Pool(1)
null=p.map(PlotPicture,xrange(NbStp))
p.close()
##Make movies:
print('... is making the movie')
null=os.system('ffmpeg -r 15 -y -f image2 -i tmpPl/%04d.png -qscale 1 Pl.avi')
null=os.system('ffmpeg -r 15 -y -f image2 -i tmpWh/%04d.png -qscale 1 Wh.avi')
##Remove folders:
null=os.system('rm -f -R tmpPl')
null=os.system('rm -f -R tmpWh')
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Intialisation:
##Load libraries:
import numpy as np
import math as m
from scipy import misc
from scipy import signal as sg
import fnmatch
import os
import cv2
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.widgets import RectangleSelector
##Input parameter:
###Proximity threshold for root tip connection:
ThrProxConn=70
###Proximity threshold for root tip detection:
ThrProxDetec=15
##Count the number of pictures in the folder to get the number of keeped steps:
NbStp=len(fnmatch.filter(os.listdir('pictureWh'),'*.jpg'))
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Pick initial variable for the image post processing
##Load the last picture:
pict0=misc.imread('pictureWh/'+str(NbStp-1).zfill(4)+'.jpg')[:,:,0]
##Pick an intensity threshold to make mask:
###Pick an initial value
ThrdPict=(np.amax(pict0)+np.amin(pict0))/2.
flag0=1
###Pick a value on a scale until it is suitable
while flag0:
try:
pict1=pict0>ThrdPict
plt.subplot(1,2,1)
plt.imshow(pict1,cmap=plt.cm.Greys)
plt.title('threshold value: '+'%0d'%ThrdPict)
plt.subplot(1,2,2)
plt.imshow(pict0)
plt.colorbar()
plt.title('pick a threshold value on the scale \n or close')
a=plt.ginput(1,timeout=-1)
plt.close()
plt.show()
ThrdPict=(np.amax(pict0)-np.amin(pict0))*a[0][1]+np.amin(pict0)
except:
flag0=0
##Save threshold:
os.system('mkdir pictureSkeleton > /dev/null')
np.savetxt('pictureSkeleton/image_threshold.txt',np.array([ThrdPict]))
##Select the areas not to consider to follow the root:
###Define selection functions:
def line_select_callback(eclick, erelease):
global x1, y1, x2, y2
x1,y1=eclick.xdata,eclick.ydata
x2,y2=erelease.xdata,erelease.ydata
def toggle_selector(event):
print(' Key pressed.')
if event.key in ['Q', 'q'] and toggle_selector.RS.active:
print(' RectangleSelector deactivated.')
toggle_selector.RS.set_active(False)
if event.key in ['A', 'a'] and not toggle_selector.RS.active:
print(' RectangleSelector activated.')
toggle_selector.RS.set_active(True)
###Stepwise selection of the ROI:
pict1_int=1-pict1.astype('int')
flag_tog=True
pict_mask=np.ones(pict1_int.shape)
while flag_tog:
pict1_int=pict1_int*pict_mask
x1=0; y1=0; x2=0; y2=0
fig,current_ax=plt.subplots()
plt.imshow(pict1_int,cmap=plt.cm.Greys)
plt.title('select area not to consider, close to validate, close 2 times to quit')
toggle_selector.RS=RectangleSelector(current_ax,line_select_callback,drawtype='box',useblit=True,button=[1, 3],minspanx=5,minspany=5,spancoords='pixels',interactive=True)
plt.connect('key_press_event',toggle_selector)
plt.show()
plt.close()
if (x1>0 or x2>0):
pict_mask[int(y1):int(y2),int(x1):int(x2)]=0
else:
break
###Save mask:
misc.imsave('pictureSkeleton/ROI_mask.png',pict_mask)
##Select seed:
###Load the last picture:
pict0=misc.imread('pictureWh/'+'%04d'%(0)+'.jpg')[:,:,0]
###Select:
pict1=pict0>ThrdPict
pict1=(pict1.astype(int)-pict_mask)<0
plt.imshow(pict1,cmap=plt.cm.Greys)
plt.title('select 2 points to zoom on the root top')
a=plt.ginput(2,timeout=-1)
plt.axis([min(a[0][0],a[1][0]),max(a[0][0],a[1][0]),max(a[0][1],a[1][1]),min(a[0][1],a[1][1])])
plt.title('zoom and clic on the head of the root and close')
JIseed=plt.ginput(1,timeout=-1)
plt.close()
#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#~/"\~#
#Extract the mask root network:
##Extraction for the last image:
###Compute the connected areas:
pict3=np.uint8(misc.imread('pictureWh/'+str(NbStp-1).zfill(4)+'.jpg')[:,:,0])
pict3=(((pict3>ThrdPict).astype(int)-pict_mask)<0).astype(int)