diff --git a/Generating_a_Training_Set/Step1_SelectRandomFrames_fromVideos.py b/Generating_a_Training_Set/Step1_SelectRandomFrames_fromVideos.py index f47b91280..786e26795 100644 --- a/Generating_a_Training_Set/Step1_SelectRandomFrames_fromVideos.py +++ b/Generating_a_Training_Set/Step1_SelectRandomFrames_fromVideos.py @@ -29,6 +29,7 @@ import os import math import sys + sys.path.append(os.getcwd().split('Generating_a_Training_Set')[0]) from myconfig import Task, videopath, videotype, filename, x1, x2, y1, y2, start, stop, \ date, cropping, numframes2pick, selectionalgorithm, checkcropping diff --git a/Generating_a_Training_Set/frameselectiontools.py b/Generating_a_Training_Set/frameselectiontools.py index 878295396..c6942e6d4 100755 --- a/Generating_a_Training_Set/frameselectiontools.py +++ b/Generating_a_Training_Set/frameselectiontools.py @@ -18,9 +18,14 @@ from tqdm import tqdm def UniformFrames(clip,numframes2pick,start,stop,Index="all"): - ''' Temporally uniformly sampling frames in interval (start,stop). Visual information of video is irrelevant for this method. This code is - very fast and sufficient (to extract distinct frames) when behavioral videos naturally covers many states. ''' + ''' Temporally uniformly sampling frames in interval (start,stop). + Visual information of video is irrelevant for this method. This code is fast and sufficient (to extract distinct frames), + when behavioral videos naturally covers many states. + + The variable Index allows to pass on a subindex for the frames. + ''' print("Uniformly extracting of frames from", start*clip.duration," seconds to", stop*clip.duration, " seconds.") + if Index=="all": if start==0: frames2pick = np.random.choice(math.ceil(clip.duration * clip.fps * stop), size=numframes2pick - 1, replace = False) @@ -30,23 +35,28 @@ def UniformFrames(clip,numframes2pick,start,stop,Index="all"): else: startindex=int(np.floor(clip.fps*clip.duration*start)) stopindex=int(np.ceil(clip.fps*clip.duration*stop)) - Index=np.array(Index) + Index=np.array(Index,dtype=np.int) Index=Index[(Index>startindex)*(Index=numframes2pick-1: - return list(np.random.permutation(Index)[:numframes2pick-1]+startindex) + return list(np.random.permutation(Index)[:numframes2pick-1]) else: return list(Index) def KmeansbasedFrameselection(clip,numframes2pick,start,stop,Index="all",resizewidth=30,batchsize=100,max_iter=50): - ''' This code downsamples the video to a width of resizewidth. The video is extracted as a numpy array, which is then - clustered with kmeans whereby each frames is treated as a vector. Frames from different clusters are then selected for labeling. This - procedure makes sure that the frames "look different", i.e. different postures etc. - On large videos this code is slow. Consider not extracting the frames from the whole video but rather set start and stop to a period around interesting behavior. + ''' This code downsamples the video to a width of resizewidth. + + The video is extracted as a numpy array, which is then clustered with kmeans, whereby each frames is treated as a vector. + Frames from different clusters are then selected for labeling. This procedure makes sure that the frames "look different", + i.e. different postures etc. On large videos this code is slow. + + Consider not extracting the frames from the whole video but rather set start and stop to a period around interesting behavior. + Note: this method can return fewer images than numframes2pick-1.''' print("Kmeans-quantization based extracting of frames from", start*clip.duration," seconds to", stop*clip.duration, " seconds.") startindex=int(np.floor(clip.fps*clip.duration*start)) stopindex=int(np.ceil(clip.fps*clip.duration*stop)) + if Index=="all": Index=np.arange(stopindex-startindex)+startindex else: @@ -68,22 +78,23 @@ def KmeansbasedFrameselection(clip,numframes2pick,start,stop,Index="all",resizew else: ncolors=1 - print("Extracting...",nframes, " (this might take a while).") + print("Extracting and downsampling...",nframes, " frames from the video.") for counter,index in tqdm(enumerate(Index)): if ncolors==1: - DATA[counter,:,:] = img_as_ubyte(clipresized.get_frame(start+index * 1. / clipresized.fps)) - else: #attention averages over color channels to keep size small / perhaps you want to use color information? - DATA[counter,:,:] = img_as_ubyte(np.array(np.mean(clipresized.get_frame(start+index * 1. / clipresized.fps),2),dtype=np.uint8)) + DATA[counter,:,:] = img_as_ubyte(clipresized.get_frame(index * 1. / clipresized.fps)) + else: #attention: averages over color channels to keep size small / perhaps you want to use color information? + DATA[counter,:,:] = img_as_ubyte(np.array(np.mean(clipresized.get_frame(index * 1. / clipresized.fps),2),dtype=np.uint8)) - print("Kmeans clustering...(this might take a while).") + print("Kmeans clustering ... (this might take a while)") data = DATA - DATA.mean(axis=0) data=data.reshape(nframes,-1) #stacking + kmeans=MiniBatchKMeans(n_clusters=numframes2pick - 1, tol=1e-3, batch_size=batchsize,max_iter=max_iter) kmeans.fit(data) - frames2pick=[] for clusterid in range(numframes2pick - 1): #pick one frame per cluster clusterids=np.where(clusterid==kmeans.labels_)[0] + numimagesofcluster=len(clusterids) if numimagesofcluster>0: frames2pick.append(Index[clusterids[np.random.randint(numimagesofcluster)]]) diff --git a/dlcDependenciesFORWINDOWS.yaml b/conda-files/dlcDependenciesFORWINDOWS.yaml similarity index 98% rename from dlcDependenciesFORWINDOWS.yaml rename to conda-files/dlcDependenciesFORWINDOWS.yaml index aa725be4f..d812ec50a 100644 --- a/dlcDependenciesFORWINDOWS.yaml +++ b/conda-files/dlcDependenciesFORWINDOWS.yaml @@ -71,6 +71,7 @@ dependencies: - pyyaml==3.12 - requests==2.19.1 - scikit-image==0.14.0 + - scikit-learn==0.19.2 - scipy==1.1.0 - simplegeneric==0.8.1 - sk-video==1.1.10 diff --git a/dlcDependenciesFORWINDOWSwTF.yaml b/conda-files/dlcDependenciesFORWINDOWSwTF.yaml similarity index 98% rename from dlcDependenciesFORWINDOWSwTF.yaml rename to conda-files/dlcDependenciesFORWINDOWSwTF.yaml index 3e6a2ffc6..5adc7580d 100644 --- a/dlcDependenciesFORWINDOWSwTF.yaml +++ b/conda-files/dlcDependenciesFORWINDOWSwTF.yaml @@ -71,6 +71,7 @@ dependencies: - pyyaml==3.12 - requests==2.19.1 - scikit-image==0.14.0 + - scikit-learn==0.19.2 - scipy==1.1.0 - simplegeneric==0.8.1 - sk-video==1.1.10 diff --git a/dlcdependencies.yml b/conda-files/dlcdependencies.yml similarity index 86% rename from dlcdependencies.yml rename to conda-files/dlcdependencies.yml index cbd80bf78..bab630349 100644 --- a/dlcdependencies.yml +++ b/conda-files/dlcdependencies.yml @@ -20,15 +20,19 @@ dependencies: - xz=5.2.4=h14c3975_4 - zlib=1.2.11=ha838bed_2 - pip: + - backports.weakref==1.0rc1 + - bleach==1.5.0 - chardet==3.0.4 - cloudpickle==0.5.3 - cycler==0.10.0 - dask==0.18.0 - decorator==4.3.0 - easydict==1.7 + - html5lib==0.9999999 - idna==2.7 - imageio==2.3.0 - kiwisolver==1.0.1 + - markdown==2.6.11 - matplotlib==2.2.2 - moviepy==0.2.3.5 - networkx==2.1 @@ -36,6 +40,7 @@ dependencies: - numpy==1.14.5 - pandas==0.23.1 - pillow==5.1.0 + - protobuf==3.6.0 - pyparsing==2.2.0 - python-dateutil==2.7.3 - pytz==2018.4 @@ -43,11 +48,14 @@ dependencies: - pyyaml==3.12 - requests==2.19.1 - scikit-image==0.14.0 + - scikit-learn==0.19.2 - scipy==1.1.0 - six==1.11.0 - sk-video==1.1.10 + - sklearn==0.0 - tables==3.4.4 - toolz==0.9.0 - tqdm==4.23.4 - urllib3==1.23 + - werkzeug==0.14.1 diff --git a/dlcdependencieswTF1.2.yml b/conda-files/dlcdependencieswTF1.2.yml similarity index 96% rename from dlcdependencieswTF1.2.yml rename to conda-files/dlcdependencieswTF1.2.yml index fd41f64d8..acaaf982c 100644 --- a/dlcdependencieswTF1.2.yml +++ b/conda-files/dlcdependencieswTF1.2.yml @@ -48,9 +48,11 @@ dependencies: - pyyaml==3.12 - requests==2.19.1 - scikit-image==0.14.0 + - scikit-learn==0.19.2 - scipy==1.1.0 - six==1.11.0 - sk-video==1.1.10 + - sklearn==0.0 - tables==3.4.4 - tensorflow==1.2.1 - toolz==0.9.0 diff --git a/docs/installation.md b/docs/installation.md index 128324ddd..0f6e2cb3a 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -17,7 +17,7 @@ For reference, we use e.g. Dell workstations (79xx series) with Ubuntu 16.04 LTS [Anaconda](https://anaconda.org/anaconda/python) is perhaps the easiest way to install Python and additional packages across various operating systems. With anaconda just create all the dependencies in an [environment](https://conda.io/docs/user-guide/tasks/manage-environments.html) on your machine by running in a terminal: ``` git clone https://github.com/AlexEMG/DeepLabCut.git -cd DeepLabCut +cd DeepLabCut/conda-files conda env create -f dlcdependencieswTF1.2.yml ``` diff --git a/myconfig.py b/myconfig.py index 096a3cd0f..bdc2932b1 100644 --- a/myconfig.py +++ b/myconfig.py @@ -33,13 +33,13 @@ y2 = 624 # Portion of the video to sample from in step 1 (In relative terms of video length, i.e. [0,1] is the full video) -start = 0 +start = 0.1 stop =1 # Number of frames to pick numframes2pick = 22 -# Method to pick frames: +# Method to pick frames: uniform or kmeans selectionalgorithm='uniform' # the algorithm 'uniform' temporally uniformly sampes frames in interval (start,stop). Visual information within video is irrelevant for this method. This code is very fast and sufficient (to extract distinct frames) when behavioral videos naturally covers many states.