Create Anaglyph (GIMP Plugin)
anaglyph_algorithm.py
Go to the documentation of this file.
1 from gimpfu import *
2 import numpy
3 
4 # interp2-like function from matlab
5 def interp2(X,Y,Z):
6  """! interpolates Z at locations X,Y
7  output of function is of shape(X)==shape(Y)
8  """
9  from numpy import *
10  X1 = array(floor(X),dtype=int);
11  X2 = array(ceil(X),dtype=int);
12  Y1 = array(floor(Y),dtype=int);
13  Y2 = array(ceil(Y),dtype=int);
14 
15  M1 = logical_or(logical_or(Y1<0,Y1>=Z.shape[0]),logical_or(Y2<0,Y2>=Z.shape[0]))
16  M2 = logical_or(logical_or(X1<0,X1>=Z.shape[1]),logical_or(X2<0,X2>=Z.shape[1]))
17  M = logical_not(logical_or(M1,M2));
18 
19  X1[X1<0]=0;
20  X1[X1>=Z.shape[1]]=Z.shape[1]-1;
21  X2[X2<0]=0;
22  X2[X2>=Z.shape[1]]=Z.shape[1]-1;
23  XR = X-X1;
24  Y1[Y1<0]=0;
25  Y1[Y1>=Z.shape[0]]=Z.shape[0]-1;
26  Y2[Y2<0]=0;
27  Y2[Y2>=Z.shape[0]]=Z.shape[0]-1;
28  YR = Y-Y1;
29  ERG1 = Z[Y1,X1]+(Z[Y1,X2]-Z[Y1,X1])*XR;
30  ERG2 = Z[Y2,X1]+(Z[Y2,X2]-Z[Y2,X1])*XR;
31  ERG = ERG1+(ERG2-ERG1)*YR;
32  return ERG,M;
33 
34 class Anaglyph:
35  """! This class represents an algorithm to compute two stereo images from gimp layers and to combine them to an anaglyph. """
36  def __init__(self, f1=1.0, f2=1.0):
37  """! Creates an anaglyph algorithm.
38  @param f1 the darkening factor for the left image (1.0 = no modification)
39  @param f2 the darkening factor for the left image (1.0 = no modification)
40  """
41  self.f1=f1
42  self.f2=f2
43  self.imsum = None
44  self.left = None
45  self.right = None
46  self.aleft = None
47  self.aright = None
48 
49  def shiftx(self,img,d):
50  """! Helper function to shift an image with a given disparity value. """
51  res = numpy.roll(img,d,axis=1)
52  if (d>0):
53  res[:,:d]=0
54  elif (d<0):
55  res[:,d:]=0
56  return res
57 
58  def shiftx_ext(self,img,d):
59  """! Helper function to shift an image with a given disparity map. """
60  w = d.shape[1]
61  h = d.shape[0]
62  x,y = numpy.meshgrid(numpy.arange(w),numpy.arange(h))
63  x = x-d
64  res,m = interp2(x,y,img);
65  return res*m
66 
67 
68  def update(self, layer_data, d):
69  """! Update the image using a single depth value
70  @param layer_data the layer to be added (as numpy array)
71  @param d the disparity of the layer
72  """
73  h = layer_data.shape[0]
74  w = layer_data.shape[1]
75  if layer_data.shape[2]==1:
76  tmp = numpy.ones((h,w,2))*255.0
77  tmp[:,:,1]=numpy.reshape(layer_data,(h,w))
78  layer_data=tmp
79  if self.left==None:
80  self.left = numpy.zeros((h,w))
81  self.right = numpy.zeros((h,w))
82  self.aleft = numpy.zeros((h,w))
83  self.aright = numpy.zeros((h,w))
84  else:
85  assert(self.left.shape == (h,w), "shape must not change")
86 
87  imleft = self.shiftx(layer_data[:,:,0],-d)
88  imright = self.shiftx(layer_data[:,:,0],+d)
89  alphaleft = self.shiftx(layer_data[:,:,1],-d)
90  alpharight = self.shiftx(layer_data[:,:,1],+d)
91 
92  self.left = (self.left *(255-alphaleft )+imleft *alphaleft )/255
93  self.right = (self.right*(255-alpharight)+imright*alpharight)/255
94  self.aleft = numpy.maximum(alphaleft, self.aleft)
95  self.aright = numpy.maximum(alpharight, self.aright)
96 
97  def update_ext(self, layer_data, d):
98  """! Update the image using a depth map
99  @param layer_data the layer to be added (as numpy array)
100  @param d the disparity map of the layer
101  """
102  h = layer_data.shape[0]
103  w = layer_data.shape[1]
104  if self.left==None:
105  self.left = numpy.zeros((h,w))
106  self.right = numpy.zeros((h,w))
107  self.aleft = numpy.zeros((h,w))
108  self.aright = numpy.zeros((h,w))
109  else:
110  assert(self.left.shape == (h,w), "shape must not change")
111 
112  imleft = self.shiftx_ext(layer_data[:,:,0],-d)
113  imright = self.shiftx_ext(layer_data[:,:,0],+d)
114  alphaleft = self.shiftx_ext(layer_data[:,:,1],-d)
115  alpharight = self.shiftx_ext(layer_data[:,:,1],+d)
116 
117  self.left = (self.left *(255-alphaleft )+imleft *alphaleft )/255
118  self.right = (self.right*(255-alpharight)+imright*alpharight)/255
119  self.aleft = numpy.maximum(alphaleft, self.aleft)
120  self.aright = numpy.maximum(alpharight, self.aright)
121 
122  def get_result(self,swap_lr):
123  """! Combines the result collected so far (left and right image) as anaglyph.
124  @param swap_lr if true the left and right image are swapped.
125  @return a numpy array representing the result image with 4 (RGBA) channels.
126  """
127  a = numpy.zeros((self.left.shape[0],self.left.shape[1],4))
128  if swap_lr:
129  r = self.left
130  l = self.right
131  else:
132  l = self.left
133  r = self.right
134  a[:,:,0] = l*self.f1 + (1-self.f1)/2
135  a[:,:,1] = r*self.f2 + (1-self.f2)/2
136  a[:,:,2] = r*self.f2 + (1-self.f2)/2
137  a[:,:,3] = numpy.maximum(self.aleft,self.aright)
138  return a
def shiftx_ext(self, img, d)
Helper function to shift an image with a given disparity map.
def update_ext(self, layer_data, d)
Update the image using a depth map.
This class represents an algorithm to compute two stereo images from gimp layers and to combine them ...
def get_result(self, swap_lr)
Combines the result collected so far (left and right image) as anaglyph.
def shiftx(self, img, d)
Helper function to shift an image with a given disparity value.
def __init__(self, f1=1.0, f2=1.0)
Creates an anaglyph algorithm.
def interp2(X, Y, Z)
interpolates Z at locations X,Y output of function is of shape(X)==shape(Y)
def update(self, layer_data, d)
Update the image using a single depth value.