Create Anaglyph (GIMP Plugin)
depth_algorithm.py
Go to the documentation of this file.
1 import re
2 from gimpfu_numpy_converter import *
3 
4 class DepthAlgo:
5  """!
6  This class is responsible to compute the depth of a layer. This can be a single depth value or a depth map.
7  """
8  def __init__(self, gimp_image, mindisp, maxdisp):
9  """!
10  Creates a DepthAlgo.
11  @param gimp_image the gimp image to be processed
12  @param min_disp the minimum disparity to be processed (relative to image width)
13  @param max_disp the maximum disparity to be processed (relative to image width)
14  """
15  self.gimp_image = gimp_image
16  self.mindisp = mindisp
17  self.maxdisp = maxdisp
18  self.n=0
19  self.depthmaps={}
20  self.normallayers=[]
21  for layer in reversed(gimp_image.layers):
22  m = self.is_depth_map(layer)
23  isnormal = not( m or self.has_fixdepthmap(layer) or self.has_depth(layer))
24  if isnormal:
25  #print("normal layer: %s --> %d"%(layer.name,self.n))
26  self.n+=1
27  self.normallayers.insert(0,layer)
28  elif m:
29  data = layer2array(layer, dtype=numpy.float)
30  data = data[:,:,0]
31  assert(data.max()>data.min())
32  data = (data-data.min())/(data.max()-data.min())*1.0
33  mi = float(m.group(2))
34  ma = float(m.group(3))
35  assert(ma>mi)
36  self.depthmaps[m.group(1)] = mi+data*(ma-mi)
37  #print("layer count n==%d"%(self.n))
38 
39 
40  def is_depth_map(self, gimp_layer):
41  """!
42  Determines if a layer is a depth map.
43  @param gimp_layer the layer to be investigated.
44  @return the matcher containing (name, mindepth, maxdepth) or None (logically maps to a boolean)
45  """
46  pat = re.compile(r'depthmap\s+(\w+)\s+(-?[\d\.]+)\s+to\s+(-?[\d\.]+)')
47  m=pat.match(gimp_layer.name)
48  return m
49 
50  def has_map(self, gimp_layer):
51  """!
52  @param gimp_layer the layer to be investigated.
53  @return if this layer has a depth map (or a single depth for the whole layer)
54  """
55  return bool(self.has_reldepthmap(gimp_layer)) or bool(self.has_fixdepthmap(gimp_layer))
56 
57  def has_reldepthmap(self, gimp_layer):
58  """! Determines if a layer has (uses) a depth map as relative map (relative depth values between the neighboring layers)
59  @param gimp_layer the layer to be investigated.
60  @return the matcher containing the map name or None (logically maps to a boolean)
61  """
62  pat = re.compile(r'reldepthmap\s*=\s*(\w+)')
63  m=pat.match(gimp_layer.name)
64  return m
65 
66  def has_fixdepthmap(self, gimp_layer):
67  """! Determines if a layer has (uses) a depth map as fixed map fixed depth values)
68  @param gimp_layer the layer to be investigated.
69  @return the matcher containing the map name or None (logically maps to a boolean)
70  """
71  pat = re.compile(r'fixdepthmap\s*=\s*(\w+)')
72  m=pat.match(gimp_layer.name)
73  return m
74 
75  def has_depth(self, gimp_layer):
76  """! Determines if a used depth is specified for the layer
77  @param gimp_layer the layer to be investigated.
78  @return the matcher containing the map depth (logically maps to a boolean)
79  """
80  n=gimp_layer.name
81  if (n.startswith("background")):
82  n="depth=0"
83  pat = re.compile(r'depth=(-?[\d\.]+)')
84  m=pat.match(n)
85  return m
86 
87  def get_disparity(self, gimp_layer):
88  """! Determines the depth value or the map of depth values of a layer
89  @param gimp_layer the layer to be investigated.
90  @retrun the depth value (as absolute disparity in pixels) either as single value or as array of values.
91  """
92  idx = self.gimp_image.layers.index(gimp_layer) # raises exception on error
93  mrel=self.has_reldepthmap(gimp_layer)
94  mfix=self.has_fixdepthmap(gimp_layer)
95  if self.n>1:
96  d = float(idx)/float(self.n-1)
97  else:
98  d = 0
99  if self.has_map(gimp_layer):
100  if mrel:
101  print("relative map detected: "+gimp_layer.name)
102  d0 = d-float(1.0/(self.n-1))
103  d1 = d+float(1.0/(self.n-1))
104  assert(mrel.group(1) in self.depthmaps.keys())
105  d = self.depthmaps[mrel.group(1)]
106  d = d0+d*(d1-d0)
107  else:
108  print("fixed map detected: "+gimp_layer.name)
109  assert(mfix.group(1) in self.depthmaps.keys())
110  d = self.depthmaps[mfix.group(1)]
111  d = self.mindisp+float(self.maxdisp-self.mindisp)*d
112  return numpy.floor(0.5+d*self.gimp_image.width/100.0)
113  else:
114  m=self.has_depth(gimp_layer)
115  if (m):
116  d = float(m.group(1))
117  #print("detected fixed depth: %s=rel. %f"%(gimp_layer.name,d))
118  else:
119  idx = self.normallayers.index(gimp_layer) # raises exception on error
120  if self.n>1:
121  d = float(idx)/float(self.n-1)
122  else:
123  d = 0
124 
125  d = self.mindisp+float(self.maxdisp-self.mindisp)*d
126  #print("***** depth, idx=%d, d=%f"%(idx,d))
127  return int(0.5+d*self.gimp_image.width/100.0)
128 
129 
def has_map(self, gimp_layer)
def __init__(self, gimp_image, mindisp, maxdisp)
Creates a DepthAlgo.
def has_reldepthmap(self, gimp_layer)
Determines if a layer has (uses) a depth map as relative map (relative depth values between the neigh...
def has_fixdepthmap(self, gimp_layer)
Determines if a layer has (uses) a depth map as fixed map fixed depth values)
This class is responsible to compute the depth of a layer.
def has_depth(self, gimp_layer)
Determines if a used depth is specified for the layer.
def layer2array(layer, dtype=None)
converts a layer to an array.
def get_disparity(self, gimp_layer)
Determines the depth value or the map of depth values of a layer.
def is_depth_map(self, gimp_layer)
Determines if a layer is a depth map.