IN_IDLE = 0 ############################################################ ## Autostereogramme / hidden surface removal, oversampling, ## symmetrisch rechts-links texturiert ## Wolfgang.Urban@schule.at ############################################################ DPI = 75 # inch resolution of display media OBSDIST = 12 # inch distance of observer to media MINDEPTH = 4 # (0=screen) MAXDEPTH = 12 # (12=back=OBSDIST) USE_PATTERNMID = 1 # x symmetrisch aus der Mitte ########################################################################### from Tkinter import * import tkFileDialog class Autostereo: def __init__(self): self.root = Tk() self.root.title("HIB Stereograms - by w.u.") self.l_status = Label(self.root,font=("Arial",14)) self.l_status.pack(side=BOTTOM) self.buildbuttons() self.l_depth = Label(self.root) self.l_depth.pack(side=RIGHT) self.l_pattern = Label(self.root) self.l_pattern.pack(side=LEFT,anchor=N) self.root.update() self.patternimage = None self.depthimage = None self.pattern_valid = False self.depth_valid = False self.RUNNING = False if not IN_IDLE: self.root.mainloop() ################################################################### def loadpattern(self,name=None): if name==None: name = self.filedialog(2) if not name: return self.showstatus("loading texture image") self.patternimage = PhotoImage(file=name) self.pat_sx,self.pat_sy = self.patternimage.width(),self.patternimage.height() self.l_pattern.configure(image=self.patternimage) self.l_pattern.update() self.pattern = None self.pattern_valid = False self.showstatus("texture loaded") def loaddepth(self,name=None): if name==None: name = self.filedialog(1) if not name: return self.showstatus("loading depth image") self.depthimage = PhotoImage(file=name) self.sizex,self.sizey = self.depthimage.width(),self.depthimage.height() self.l_depth.configure(image=self.depthimage) self.l_depth.update() self.depth = None self.depth_valid = False self.showstatus("depth image loaded") def analyzepattern(self,num_x): if self.pattern_valid: return if self.patternimage == None: self.showstatus("texturepattern - image not loaded!") return if self.pat_sx < num_x: self.showstatus("texture width is %d, but we need %d"%(self.pat_sx,num_x)) return self.showstatus("analyzing texture image") self.STOPPER = False pic = [] if USE_PATTERNMID: x0 = (self.pat_sx-num_x)/2 else: x0 = 0 pi = self.patternimage fact = 100.0/self.pat_sy perc = -1 ## string of 3 color values converted to tuple (r,g,b) for y in range(self.pat_sy): if self.STOPPER: return line = [] for x in range(x0,x0+num_x): line.append( tuple(map(int, pi.get(x,y).split())) ) pic.append(line) ## line y done newperc = int(0.5+fact*y) if newperc != perc: self.showstatus("analyzing texture image: %2d%%"%int(0.5+fact*y)) perc = newperc self.pattern = pic self.pattern_valid = True def analyzedepth(self): if self.depth_valid: return if self.depthimage == None: self.showstatus("depth-image not loaded!") self.showstatus("analyzingdepth image") self.STOPPER = False pic = [] di = self.depthimage fact = 100.0/self.sizey perc = -1 ## color grey values to string of chars for y in range(self.sizey): if self.STOPPER: return line = [] for x in range(self.sizex): col = di.get(x,y).split() line.append(chr(int(col[0]))) pic.append("".join(line)) ## line y done newperc = int(0.5+fact*y) if newperc != perc: self.showstatus("analyzing depth image: %2d%%"%newperc) perc = newperc self.depth = pic self.depth_valid = True def getpattern(self,x,y): return self.pattern[y][x] def getdepth(self,x,y): return ord(self.depth[y][x]) def plotstereoline(self,color,y,vwidth,oversam): # downsample color[] to colorline[] using medium color newline = [] for x in range(0,vwidth,oversam): r,g,b = 0,0,0 for i in range(x,x+oversam): col = color[i] r += col[0] g += col[1] b += col[2] r = r/oversam g = g/oversam b = b/oversam newline.append("#%02x%02x%02x"%(r,g,b)) self.depthimage.put((tuple(newline),),(0,y)) self.root.update() def showstatus(self,text): self.l_status.configure(text=text) self.l_status.update() # ideal (i.e. minimum = used) pattern width def getidealpatternwidth(self): xdpi, ydpi = DPI,DPI obsDist = xdpi*OBSDIST eyeSep = int(xdpi*2.5) maxdepth = xdpi*12 maxsep = int(float(eyeSep)*maxdepth/(maxdepth+obsDist)) return maxsep ##uses : self.sizex/y of depth, self.pat_sx/y of pattern ## getdepth(x,y), getpattern(x,y) ## plotstereoline(colortuples,y) ## analyzedepth/pattern builds color arrays def create(self,oversam=4): self.STOPPER = False self.RUNNING = True xdpi, ydpi = DPI,DPI # resolution obsDist = xdpi*OBSDIST # observer distance (pixels) eyeSep = int(xdpi*2.5) # eye separation maxdepth = xdpi*MAXDEPTH # maximum depth mindepth = xdpi*MINDEPTH # minimal depth self.analyzedepth() # prepare depth data if not self.depth_valid: self.RUNNING = False return # maximal separation equals used width of texture pattern maxsep = int(float(eyeSep)*maxdepth/(maxdepth+obsDist)) vmaxsep = maxsep*oversam # virtual max separation veyeSep = eyeSep*oversam # virtual eye separation self.analyzepattern(maxsep) # prepare texture data if not self.pattern_valid: self.RUNNING = False return width, height = self.sizex, self.sizey # image size vwidth = width*oversam # virtual width patwidth,patheight = self.pat_sx, self.pat_sy # pattern size vpatwidth = patwidth*oversam # virtual pattern width yShift = ydpi/16 # for wobbled filling s = vwidth/2-vmaxsep/2 # poffset = vmaxsep-(s%vmaxsep) # pattern ends match in middle self.showstatus("transforming...") totalwidth = width*oversam lookL, lookR = [0]*totalwidth, [0]*totalwidth color = [0]*totalwidth # assigned colors colorline = [0]*width # colors for output (downsampled) for y in range(height): # process each line if self.STOPPER: self.RUNNING = False return for x in range(vwidth): # unlink all points lookL[x] = x lookR[x] = x # get local separation from depth image for x in range(vwidth): if (x%oversam)==0: z = self.getdepth(x/oversam,y) featureZ = int(maxdepth-(maxdepth-mindepth)*z/256.0) sep = int(float(veyeSep*featureZ)/(featureZ+obsDist)) left = x-sep/2 right = left+sep vis = True # hidden surface removal if (left>=0) and (rightright: lookL[lookR[left]] = lookR[left] lookR[left] = left else: vis = False if vis: lookL[right] = left lookR[left] = right # process colors from middle to right border lastlinked = -1000 for x in range(s,vwidth): if lookL[x]==x or lookL[x]