Commit bd495ef3 authored by Niels-Oliver Walkowski's avatar Niels-Oliver Walkowski
Browse files

feat(corpus): Corpus tableaus for specific contrast

Adds a method to the Corpus class which allows to arrange all diagrams
for a specific contrast and representation of all movies  together in
one tableau of diagrams.
parent 084f6bd9
import pathlib
from pathlib import Path
from cv2 import imread, imwrite
import numpy as np
from .movie import Movie
SUMMARY = {'seqmean': {'monochromatic': ['luminance'],
......@@ -11,13 +13,13 @@ SUMMARY = {'seqmean': {'monochromatic': ['luminance'],
class Corpus(object):
"""Main class for working with a corpus of movies and movie data
Attributes:
basedir (pathlib.Path) -- The root directory in which all moviefolders
basedir (Path) -- The root directory in which all moviefolders
together with their data reside.
"""
def __init__(self, path='./', summary=False):
self.basedir = pathlib.Path(path)
self.basedir = Path(path)
self.summary = summary if summary else SUMMARY
self.status = self._report() # Aktualisieren nach jeder Digitalisier.
self.movies = self._instantiate_movies()
......@@ -33,7 +35,7 @@ class Corpus(object):
"""
# get project directory
status = {}
korpus_dir = pathlib.Path(self.basedir).resolve()
korpus_dir = Path(self.basedir).resolve()
movie_dirs = [d for d in korpus_dir.iterdir() if d.is_dir()]
# filter dot paths and tmp folders
movie_dirs = [d for d in movie_dirs if not('.' in str(d.name)[0]) and
......@@ -124,3 +126,130 @@ class Corpus(object):
def _extract_contrast(self):
pass
def tableau(self,
shape='distribution',
ctrst='monochromatic',
meth='luminance',
write=True):
"""Creates a tableau of available diagrams for a given contrast
Diagrams for the tableau will not be created in case some of the movies
in the corpus lack thre required diagram. Consequently, the tableau
will only show diagrams from movies in the corpus that exist already.
Keyword Arguments:
shape {str} -- The shape of the data in the diagram. Can be one of
seqmean or distribution (default: {'distribution'})
ctrst {str} -- The name of the contrast.
(default: {'monochromatic'})
meth {str} -- The method used in order to calculate the contrast
(default: {'luminance'})
write {bool} -- Decide, if the tableau image should be written to
disk in the corpus folder or not. (default: {True})
Returns:
numpy.ndarray -- A numpy ndarry with the data type uint8
showing the tableau as an image.
"""
components = self._filter_diagrams(shape=shape, ctrst=ctrst, meth=meth)
layout = self.layout_tableau(len(components))
tableau = self._fit_components(components, layout)
if write:
imwrite('tableau.png', tableau)
return tableau
def _filter_diagrams(self,
shape='distribution',
ctrst='monochromatic',
meth='luminance'):
"""Filters which diagrams in a corpus belong to a specific contrast
The filter looks for diagrams represented in *.png files only
Keyword Arguments:
shape {str} -- The shape of the data in the diagram. Can be one of
seqmean or distribution (default: {'distribution'})
ctrst {str} -- The name of the contrast.
(default: {'monochromatic'})
meth {str} -- The method used in order to calculate the contrast
(default: {'luminance'})
Returns:
[pathlib.Path] -- A list of file paths to the diagrams that match
the selected contrast visualization.
Todo:
* FEATURE Parametize the file-format instead of looking at png
files only.
"""
diagrams = []
for k, v in self.status.items():
if shape in v['visuals'].keys():
if ctrst in v['visuals'][shape].keys():
if meth in v['visuals'][shape][ctrst].keys():
diagrams.append(Path((self.basedir / k) /
(k + '_' + shape + '_' + ctrst + '_' +
meth + '_4fps.png')))
return diagrams
@staticmethod
def layout_tableau(n, ratio=12):
"""Calculates the shape of a tableau for a given number of diagrams
Arguments:
n {int} -- The number of diagrams that should fit into the tableau
Keyword Arguments:
ratio {int} -- The number of rows that should be created before a
new column is created (default: {12})
Returns:
(int, int, int) -- A tuple with three values describing the number
of rows and the number of columns so that the diagrams fit into
it considering the given row/column ratio (n) as well as the
of missing placeholder images in order to fill-up the whole
tableau.
"""
cols, r = divmod(n, ratio)
rows = divmod(n, cols)[0]
if r > 0:
rows += 1
return (rows, cols, r)
@staticmethod
def _fit_components(components, layout):
"""Builds a tablea out of diagrams in a given layout
First, the method creates a list of col diagrams for one row. Then
this list is stacked to create one row image. This is repeated for
each row so that the result is a list of row images. Again this
is stacked to one image with is the tableau image.
Arguments:
components {[pathlib.Path]} -- A list of file paths to the
diagram image files.
layout {(int, int, int)} -- A tuple describing the number of
diagrams for each row, column as well as the differance of
available diagrams and places in the tableau.
Returns:
numpy.ndarray -- A numpy ndarry with the data type uint8
showing the tableau as an image.
"""
tableau = []
for row in range(layout[0]):
column = []
for col in range(layout[1]):
n = row * layout[1] + col
try:
img = imread(str(components[n]))
# Create dummy images to fill-up the remaining space in the
# tableau
except IndexError:
img = np.full((1200, 16000, 3), (255, 255, 255))
column.append(img)
column = np.hstack(column)
tableau.append(column)
tableau = np.vstack(tableau)
return tableau
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment