def on_press(self): # Setup the scatter layout to show in the popup scatter = Scatter(do_rotation=False, size_int=(300, 300), scale_min=1.0, scale_max=10.0) image_source = join(globals_.photo_path, 'thumbs', basename(self.source)) image = AsyncImage(source=image_source) scatter.add_widget(image) # Resize the scatter object multiplier = 6 mat = Matrix().scale(multiplier, multiplier, multiplier) scatter.apply_transform(mat) popup = Popup(title=basename(self.source), content=scatter, size_hint=(0.8, 1), pos_hint={ 'x': 0.0, 'y': 0.0 }) popup.open()
class TestCamera(App): def __init__(self, **kwargs): super(TestCamera, self).__init__(**kwargs) self._camera = None def _camera_toggle(self, val): self._camera.play = not self._camera.play def _led_toggle(self, val): if self._led_state == GPIO.LOW: self._led_state = GPIO.HIGH self._toggle.text = "LED ON" else: self._led_state = GPIO.LOW self._toggle.text = "LED OFF" GPIO.output(LED_Pin, self._led_state) def _show_demo_results(self, val): popup = Popup(title='Reconstruction Results', content=Label(text= 'TOTAL TARGET CELLS : 52\n'+ 'TOTAL FOUND CELLS : 77\n'+ 'TOTAL FILTERED CELLS : 0\n'+ 'TOTAL BEADS FOR TARGET CELLS : 235\n'+ 'AVERAGE BEADS/CELL : 4'), size_hint=(None, None), size=(400, 200)) popup.open() def _show_carousel(self, log_file): local_recon = '/home/pi/recon' prefix = log_file.split('.', 1)[0] carousel = Carousel(direction='right') for filename in os.listdir(local_recon): if filename.startswith(prefix) and filename.endswith('.png'): src = os.path.join(local_recon, filename) image = Image(source=src, allow_stretch=True, size=(620, 460)) carousel.add_widget(image) popup = Popup(title='Reconstruction Results', content=carousel, size_hint=(None, None), size=(640, 480)) popup.open() def _request_capture(self, val): self._camera.capture__full_res_frame() def _request_ref_capture(self, val): self._camera.capture__full_res_ref() def _toggle_object_detection(self, val): detecting = not self._camera.get_object_detection() self._camera.set_object_detection(detecting) if not detecting: self._object_detection.source = '/home/pi/d3-ui/img/object_detection_off.png' else: self._object_detection.source = '/home/pi/d3-ui/img/object_detection_on.png' def _change_exposure(self, instance, val): self._camera.set_exposure(int(val)) def _do_reset_scatter(self, val): # move the mat = Matrix().scale(10,10,10).translate(0,-150,0) self._scatter.transform = mat def _auto_change_exposure(self, val): # go in steps self._auto_centroiding = True self._auto_centroid.source = '/home/pi/d3-ui/img/distribution_centroid_on.png' t = Thread(name='centroid_thread', target=self._do_auto_change_exposure) t.start() def _auto_change_exposure_done(self, l): # go in steps self._auto_centroiding = True self._auto_centroid.source = '/home/pi/d3-ui/img/distribution_centroid_off.png' # basic pid loop.... def _do_auto_change_exposure(self): epsilon = 1 previous_error = 0 integral = 0 error = 127 - self._histogram.centroid dt = 1 Kp = 0.5 #Kd = 0.6 #Ki = 0.6 Kd = 0.1 Ki = 0 tries = 0 max_tries = 15 while abs(error) > epsilon and tries < max_tries: try: integral = integral + error*dt derivative = (error - previous_error)/dt output = Kp*error + Ki*integral + Kd*derivative + self._camera.get_exposure() # set exposure to the output if(output < self._exposure_slider.max and output > self._exposure_slider.min): self._camera.set_exposure(int(output)) # let the exposure settle sleep(.4) previous_error = error error = 127 - self._histogram.centroid tries += 1 except: e = sys.exc_info()[0] Logger.exception('Exception! %s', e) Clock.schedule_once(self._auto_change_exposure_done) def _exit_app(self, val): self._camera.play = False # give it a 1/4 sec to shu down the camera sleep(0.25) App.get_running_app().stop() import sys sys.exit() def _update_histogram(self, val): frame = self._camera.get_current_frame() self._histogram.set_data(frame) #self._histogram.set_pil_image(self._camera.get_current_frame()) #npImage = np.array(frame) #hist_full = cv2.calcHist([npImage],[0],None,[256],[0,256]).ravel() #self._plot.points = [(x, hist_full[x]) for x in range(0,256)] #plt.plot(hist_full,color = 'b') #plt.clf() #plt.hist(npImage.ravel(), 256,[0,256]) #plt.xlim([0,256]) #self._histogram.draw() def _update_fps(self, l): self._fps.text = "FPS: %d" % self._camera.get_fps() self._exposure.text = "Exposure: %d" % self._camera.get_exposure() self._centroid.text = "C: %d" % self._histogram.centroid # todo: change this to be event-driven if self._camera.is_uploading(): if self._uploading.pos_hint['pos'][0] < 0: self._uploading.pos_hint = {'pos':(0.0,0.9)} self._uploadingAmt.pos_hint = {'pos': (0.0, 0.8)} self._upload_progress.pos_hint = {'pos':(0.2,0.9)} #self._demo.pos_hint = {'pos': (0.0, 0.7)} self._snap.enabled = False self._upload_progress.value = 100 * self._camera.get_uploaded_size() / self._camera.get_total_upload_size() self._uploadingAmt.text = '%d kB' % int(self._camera.get_uploaded_size() / 1000) else: if self._uploading.pos_hint['pos'][0] >= 0: try: self._uploading.pos_hint = {'pos':(-1,-1)} self._upload_progress.pos_hint = {'pos':(-1,-1)} self._uploadingAmt.pos_hint = {'pos': (-1, -1)} self._upload_progress.pos_hint = {'pos':(-1,-1)} #self._demo.pos_hint = {'pos': (-1, -1)} self._snap.enabled = True except: e = sys.exc_info()[0] Logger.exception('Exception! %s', e) def updateImages(self): if not self._is_updating: t = Thread(name='image_thread', target=self._do_download) t.start() def _do_download(self): try: self._is_updating = True local_recon ='/home/pi/recon' if not os.path.exists(local_recon): os.makedirs(local_recon) dbx = dropbox.Dropbox("Yk7MLEza3NAAAAAAAAABGyzVVQi_3q7CkUoPjSjO6tWId31ogOM0KiBcdowZoB0b") # dbx = dropbox.Dropbox("Yk7MLEza3NAAAAAAAAAAp3MyYSImy0N0-3IMflqMPenGwEWJPqxAWeOAFzKu6y9A") # remote_path = '/input_test/D3RaspberryPi/%s' % os.path.basename(file) remote_recon = '/input/D3RaspberryPi/recon/' mode = dropbox.files.WriteMode.overwrite #mtime = os.path.getmtime(file) # list the folder contents try: res = dbx.files_list_folder(remote_recon) for entry in res.entries: local_file = os.path.join(local_recon, entry.name) if not os.path.exists (local_file): # download and overwrite it md, dl_res = dbx.files_download(entry.path_lower) file = open(local_file, 'w') file.write(dl_res.content) file.close #delete items no longer in dropbox # for localfile in os.listdir(local_recon): # local_file = os.path.join(local_recon, entry.name) # if not os.path.exists (local_file): # # download and overwrite it # md, dl_res = dbx.files_download(local_file) # file = open(local_file, 'w') # file.write(dl_res.content) # file.close Clock.schedule_once(self.updateResultsButton, 0.5) except dropbox.exceptions.ApiError as err: print('*** API error', err) return None except: e = sys.exc_info()[0] Logger.exception('Exception! %s', e) Clock.schedule_once(self.updateResultsButton, 0.5) self._is_updating = False def updateResultsButton(self, dt=None): try: # todo: contact dropbox local_recon = '/home/pi/recon' for local_file in os.listdir(local_recon): if local_file.endswith('.raw.log.iphone.log'): btn = Button(text=local_file, size_hint_y=None, height=44) btn.bind(on_release=lambda btn: self._show_carousel(btn.text)) self._dropdown.add_widget(btn) except: # do nothing print('error') def build(self): GPIO.setmode(GPIO.BCM) GPIO.setup(LED_Pin, GPIO.OUT) self._led_state = GPIO.LOW GPIO.output(LED_Pin, self._led_state) #layout = BoxLayout(orientation='vertical') layout = FloatLayout(size=(800, 480), pos=(0,0)) self._toggle = ToggleButton(text='LED OFF', size_hint=(0.2,0.2), pos_hint={'pos':(0.8,0)}) self._snap = Button(text='Capture', size_hint=(0.2,0.2), pos_hint={'pos':(0.8,0.2)}) self._snapref = Button(text='Reference', size_hint=(0.2,0.2), pos_hint={'pos':(0.8,0.4)}) self._demo = Button(text='Demo Results', size_hint=(0.2,0.1), pos_hint={'pos': (0.0, 0.7)}) self._auto_centroid = ImageButton(size_hint=(0.1,0.1), pos_hint={'pos':(0.7,0)}, source='/home/pi/d3-ui/img/distribution_centroid_off.png') self._object_detection = ImageButton(size_hint=(0.1,0.1), pos_hint={'pos':(0.7,0.1)}, source='/home/pi/d3-ui/img/object_detection_off.png') self._reset_scatter = ImageButton(size_hint=(0.1,0.1), pos_hint={'pos':(0.7,0.2)}, source='/home/pi/d3-ui/img/reset_scatter.png') self._exit = Button(text='X', size_hint=(0.05,0.05), pos_hint={'pos':(0.95,0.95)}) self._fps = Label(text='FPS: 0', size_hint=(0.1,0.1), pos_hint={'pos':(0.8,0.9)}) self._uploading = Label(text='Uploading...', size_hint=(0.2,0.1), pos_hint={'pos':(-1,-1)}, color=[0,0,1,0]) self._uploadingAmt = Label(text='', size_hint=(0.2,0.1), pos_hint={'pos':(-1,-1)}, color=[0,0,1,0]) self._exposure = Label(text='Exposure: 0', size_hint=(0.2,0.1), pos_hint={'pos':(0,0)}) self._centroid = Label(text='C:0', size_hint=(0.1,0.1), pos_hint={'pos':(0.79,0.83)}, color=[1,0,0,1]) self._exposure_slider = Slider(min=0, max=2500, value=333, size_hint=(0.5,0.1), pos_hint={'pos':(0.2,0)} ) self._upload_progress = ProgressBar(max=100, size_hint=(0.5,0.1), pos_hint={'pos':(-1,-1)}) self._camera = CameraD3(resolution=(640,480), fourcc="GREY", capture_resolution=(3872, 2764), capture_fourcc="Y16 ", size_hint=(1,1), pos_hint={'pos':(0,0)}, play=True, ) self._dropdown = DropDown() # create a big main button self._imageResultsButton = Button(text='Image Explorer',pos_hint={'pos': (0.0, 0.6)}, size_hint=(0.2, 0.1)) # show the dropdown menu when the main button is released # note: all the bind() calls pass the instance of the caller (here, the # mainbutton instance) as the first argument of the callback (here, # dropdown.open.). self._imageResultsButton.bind(on_release=self._dropdown.open) # one last thing, listen for the selection in the dropdown list and # assign the data to the button text. self._dropdown.bind(on_select=lambda instance, x: setattr(self._imageResultsButton, 'text', x)) # self._camera = CameraD3(resolution=(1280,720), # play=True, fourcc="GREY") # self._camera = CameraD3(resolution=(3872, 2764), # play=True, fourcc="Y16 ") # self._camera = CameraD3(resolution=(1920,1080), # play=True, fourcc="GREY") # self._camera = CameraD3(resolution=(2560, 1920), # play=True, fourcc="GREY") self._histogram = Histogram( size_hint=(0.2,0.3), pos_hint={'pos':(0.8,0.6)}) self._demo.bind(on_press=self._show_demo_results) self._toggle.bind(on_press=self._led_toggle) self._snap.bind(on_press=self._request_capture) self._snapref.bind(on_press=self._request_ref_capture) self._exit.bind(on_press=self._exit_app) self._auto_centroid.bind(on_press=self._auto_change_exposure) self._object_detection.bind(on_press=self._toggle_object_detection) self._exposure_slider.bind(value=self._change_exposure) self._reset_scatter.bind(on_press=self._do_reset_scatter) #update.bind(on_press=self._update_histogram) self._camera.fbind('on_frame_complete',self._update_histogram) self._scatter = Scatter(size_hint=(None, None), size=(200,200),) self._scatter.add_widget(self._camera) #layout.add_widget(self._camera) layoutInner = FloatLayout(size_hint=(0.8, 1), pos_hint={'x':0,'y':0}) layoutInner.add_widget(self._scatter) layout.add_widget(layoutInner) mat = Matrix().scale(10,10,10).translate(0,-150,0) self._scatter.apply_transform(mat) layout.add_widget(self._imageResultsButton) layout.add_widget(self._uploading) layout.add_widget(self._uploadingAmt) layout.add_widget(self._demo) layout.add_widget(self._histogram) layout.add_widget(self._snap) layout.add_widget(self._snapref) layout.add_widget(self._exit) layout.add_widget(self._centroid) layout.add_widget(self._exposure_slider) layout.add_widget(self._upload_progress) layout.add_widget(self._auto_centroid) layout.add_widget(self._object_detection) layout.add_widget(self._reset_scatter) layout.add_widget(self._exposure) layout.add_widget(self._fps) Clock.schedule_interval(self._update_fps, 2) layout.add_widget(self._toggle) #layout.add_widget(update) self._is_updating = False self.updateImages() return layout
class MyApp(App): def build(self): Window.bind(on_key_down=self.on_key_down) self.loadData() self.activeTrack = None self.currentLayer = 0 self.appstructure = FloatLayout() width, height = Window.size self.menu = Menu() self.menu.onNewTrack(self.newTrack) self.menu.onNewPoint(self.newPoint) self.menu.onDeletePoint(self.deletePoint) self.menu.onSetClass(self.setClass) self.menu.onFindUnclassified(self.jumpToUnclassified) self.menu.onShowStats(self.showStats) self.menu.onSave(self.save) self.core = Scatter(auto_bring_to_front=False) self.core.add_widget(self.getCurrentLayer().getContents()) self.appstructure.add_widget(self.core) self.appstructure.add_widget(self.menu.getContents()) self.zoomSlider = Slider(orientation='vertical', min=1, max=10, size_hint=(0.05,1),pos_hint={'x':0.95}) self.zoomSlider.bind(on_touch_move=self.on_touch_move) self.zoomSlider.bind(on_touch_down=self.on_touch_down) self.zoomSlider.bind(on_touch_up=self.on_touch_up) self.appstructure.add_widget(self.zoomSlider) self.imagelabel = Label(text=self.getCurrentLayer().getSource(), size_hint=(1,0.05), pos_hint={'y':0}) self.appstructure.add_widget(self.imagelabel) self.zooming = False return self.appstructure def loadImages(self): def isImage(fname): for ext in [".png", ".jpg", ".tiff", ".jpeg", ".bmp"]: if fname.lower().endswith(ext): return True return False self.layers = [] for img in sortByFirstNumber(listdir("images")): if isImage(img): self.layers.append(Layer("images/"+img)) def loadData(self): self.loadImages() self.tracks = [] try: trackreps = load(open("saveFile.data")) except: return for trackrep in trackreps: track = Track(self.setActive) for pointrep in trackrep['points']: point = Point(pointrep[1]) track.addPoint(point, pointrep[0]) self.layers[pointrep[0]].addPoint(point) point.setPos(pointrep[1]) track.setClassification(trackrep['classification']) track.setInactive() self.tracks.append(track) def save(self): self.saveTo("backup-"+datetime.today().strftime("%Y-%m-%d-%H-%M-%S")+".data") self.saveTo("saveFile.data") def saveTo(self, fileName): #save to file ... def trackRepresentation(track): trackrep = {'classification':track.getClassification()} trackrep['points'] = [] for layer in range(len(self.layers)): point = track.getPointForLayer(layer) if point: trackrep['points'].append((layer, point.getPos())) return trackrep savetracks = [] for track in self.tracks: savetracks.append(trackRepresentation(track)) print savetracks dump(savetracks, open(fileName, 'w+')) def on_touch_down(self, slider, ev): if (slider.collide_point(ev.pos[0], ev.pos[1])): self.zooming = True def on_touch_move(self, slider, ev): if (self.zooming): zoom = self.zoomSlider.value self.core.scale = zoom def on_touch_up(self, slider, ev): self.zooming = False def showStats(self, *args): classCounts = {} for classification in classesToColours: classCounts[classification] = 0 for track in self.tracks: if track.getClassification(): classCounts[track.getClassification()] += 1 text = "" for classification in classCounts: text += " %s : %s \n"%(classification,classCounts[classification]) popup = Popup(title='Statistics', content=Label(text=text), size_hint=(None, None), size=(400, 400)) popup.open() def setClass(self, classification): if (self.activeTrack): self.activeTrack.setClassification(classification) def setActive(self, track): if (self.activeTrack): self.activeTrack.setInactive() self.activeTrack = track track.setActive() def newPoint(self): if (self.activeTrack == None): return point = Point((width/2,height/2)) if (self.activeTrack.addPoint(point, self.currentLayer)): self.getCurrentLayer().addPoint(point) def deletePoint(self): if (self.activeTrack == None): return point = self.activeTrack.getPointForLayer(self.currentLayer) if (point == None): return if not(self.activeTrack.deletePoint(self.currentLayer)): return self.getCurrentLayer().deletePoint(point) if (self.activeTrack.getClassification() == None): self.tracks.remove(self.activeTrack) self.activeTrack = None def newTrack(self): track = Track(self.setActive) point = Point((width/2, height/2)) track.addPoint(point, self.currentLayer) track.setActive() track.setClassification('unclassified') self.tracks.append(track) self.setActive(track) self.getCurrentLayer().addPoint(point) def getCurrentLayer(self): return self.layers[self.currentLayer] def jumpToUnclassified(self): for track in self.tracks: if track.getClassification() == 'unclassified': for i, layer in enumerate(self.layers): if track.getPointForLayer(i): self.setActive(track) self.swapLayer(self.getCurrentLayer(), layer) self.currentLayer = i return popup = Popup(title='', content=Label(text="No unclassified tracks found!"), size_hint=(None, None), size=(400, 400)) popup.open() def moveUpLayer(self): if (self.currentLayer < (len(self.layers) - 1)): original = self.getCurrentLayer() self.currentLayer += 1 new = self.getCurrentLayer() self.swapLayer(original, new) def moveDownLayer(self): if (self.currentLayer > 0): original = self.getCurrentLayer() self.currentLayer -= 1 new = self.getCurrentLayer() self.swapLayer(original, new) def swapLayer(self, old, new): if (old == new): return self.imagelabel.text = new.getSource() self.core.add_widget(new.getContents()) self.core.remove_widget(old.getContents()) # current transform is layer * user layer = new.getTransform() transform = self.core.transform user = transform.multiply(layer.inverse()) # put back to start self.core.apply_transform(self.core.transform_inv) # apply layer transformation self.core.apply_transform(old.getTransform()) # reapply user transformation self.core.apply_transform(user) def on_key_down(self, instance, code, *args): if (code == 275): self.moveUpLayer() if (code == 276): self.moveDownLayer()
class IDSGUI(App): def __init__(self): super(IDSGUI, self).__init__() self._camera = None def _led_toggle(self, val): if self._led_state == GPIO.LOW: self._led_state = GPIO.HIGH self._toggle.text = "LED ON" else: self._led_state = GPIO.LOW self._toggle.text = "LED OFF" GPIO.output(LED_Pin, self._led_state) def _start_count(self, val): pass # fake_bin = int((np.random.randn() * 100) + 320) # self._tracker_histogram.add_track(max(0, min(640, fake_bin))) # (x,y) = self._camera.get_roi_offset() # self._camera.set_roi_offset(x+50,y+50) def _toggle_object_detection(self, val): pass # detecting = not self._camera.get_object_detection() # self._camera.set_object_detection(detecting) # if not detecting: # self._object_detection.source = self.img_path('object_detection_off.png') # else: # self._object_detection.source = self.img_path('object_detection_on.png') def _change_exposure(self, instance, val): pass # self._camera.set_exposure(int(val)) def _do_reset_scatter(self, val): # move the mat = Matrix().scale(10, 10, 10).translate(0, -150, 0) self._scatter.transform = mat def _exit_app(self, val): # self._camera.play = False # give it a 1/4 sec to shu down the camera sleep(0.25) App.get_running_app().stop() import sys sys.exit() def _update_histogram(self, val): pass # frame = self._camera.get_current_frame() # self._histogram.set_data(frame) def _update_fps(self, l): pass # self._fps.text = "FPS: %d" % self._camera.get_fps() # self._temp.text = "Temp: %s" % self._camera.get_temp() # self._exposure.text = "Exposure: %d" % self._camera.get_exposure() # self._centroid.text = "C: %d" % self._histogram.centroid def _update_roi(self, roi, roi2): pass # roi = self._roi_tracker.roi_Offset # self._camera.set_roi_offset(roi[0], roi[1]) def img_path(self, image_name): return os.path.join(os.path.dirname(__file__), 'img', image_name) def init_GPIO(self): GPIO.setmode(GPIO.BCM) GPIO.setup(LED_Pin, GPIO.OUT) self._led_state = GPIO.LOW GPIO.output(LED_Pin, self._led_state) def get_ip_address(self): try: import socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) addr = s.getsockname()[0] s.close() return addr except: return "Error" def build(self): self.init_GPIO() layout = FloatLayout(size=(800, 480), pos=(0, 0)) self._toggle = ToggleButton(text='LED OFF', size_hint=(0.2, 0.2), pos_hint={'pos': (0.8, 0)}) self._snap = Button(text='COUNT', size_hint=(0.2, 0.2), pos_hint={'pos': (0.8, 0.2)}) self._object_detection = ImageButton( size_hint=(0.1, 0.1), pos_hint={'pos': (0.7, 0.0)}, source=self.img_path('object_detection_off.png')) self._reset_scatter = ImageButton( size_hint=(0.1, 0.1), pos_hint={'pos': (0.7, 0.1)}, source=self.img_path('reset_scatter.png')) self._logo = Image(size_hint=(0.3, 0.2), pos_hint={'pos': (-0.03, 0.84)}, source=self.img_path('ids.png')) self._exit = ImageButton(size_hint=(0.05, 0.05), pos_hint={'pos': (0.96, 0.95)}, source=self.img_path('close-white.png')) red, white, kivy_blue = (1, 0, 0, 1), (1, 1, 1, 1), (51. / 255, 164. / 255, 206. / 255, 1) self._fps = Label(text='FPS: 0', size_hint=(0.1, 0.1), pos_hint={'pos': (0.8, 0.9)}, color=red) self._temp = Label(text='Temp: 0', size_hint=(0.1, 0.1), pos_hint={'pos': (0.6, 0.9)}, color=white) dev_ip = self.get_ip_address() self._ip = Label(text='IP: %s' % dev_ip, size_hint=(0.1, 0.1), pos_hint={'pos': (0.4, 0.9)}, color=white) self._exposure = Label(text='Exposure: 0', size_hint=(0.2, 0.1), pos_hint={'pos': (0, 0)}) self._centroid = Label(text='C:0', size_hint=(0.1, 0.1), pos_hint={'pos': (0.79, 0.83)}, color=white) self._exposure_slider = Slider(min=0, max=2500, value=1358, size_hint=(0.5, 0.1), pos_hint={'pos': (0.2, 0)}) # self._camera = Camera2131(resolution=(1280,960), # fourcc="GREY", # capture_resolution=(3872, 2764), # capture_fourcc="Y16 ", # size_hint=(1,1), # pos_hint={'pos':(0,0)}, # play=True, ) # self._camera = CameraIDS(resolution=(640, 480), # fourcc="GREY", # capture_resolution=(640, 480), # capture_fourcc="GREY", # size_hint=(1,1), # pos_hint={'pos':(0,0)}, # play=True) self._histogram = Histogram(size_hint=(0.2, 0.25), pos_hint={'pos': (0.8, 0.65)}) self._tracker_histogram = TrackerHistogram( size_hint=(0.2, 0.25), pos_hint={'pos': (0.8, 0.4)}) # self._roi_tracker = ROITracker(self._camera.resolution, # size_hint=(0.2,0.25), pos_hint={'pos':(0.02,0.6)}) # self._roi_tracker.bind(roi_Offset=self._update_roi) # self._demo.bind(on_press=self._show_demo_results) self._toggle.bind(on_press=self._led_toggle) self._snap.bind(on_press=self._start_count) self._exit.bind(on_press=self._exit_app) self._object_detection.bind(on_press=self._toggle_object_detection) self._exposure_slider.bind(value=self._change_exposure) self._reset_scatter.bind(on_press=self._do_reset_scatter) # self._camera.fbind('on_frame_complete',self._update_histogram) self._scatter = Scatter( size_hint=(None, None), size=(200, 200), ) # self._scatter.add_widget(self._camera) # layoutInner = FloatLayout(size_hint=(0.8, 1), pos_hint={'x':0,'y':0}) # layoutInner.add_widget(self._scatter) layout.add_widget(self._scatter) mat = Matrix().scale(10, 10, 10).translate(0, -150, 0) self._scatter.apply_transform(mat) layout.add_widget(self._histogram) layout.add_widget(self._tracker_histogram) layout.add_widget(self._snap) layout.add_widget(self._exit) layout.add_widget(self._exposure_slider) layout.add_widget(self._object_detection) layout.add_widget(self._reset_scatter) layout.add_widget(self._exposure) layout.add_widget(self._fps) layout.add_widget(self._temp) layout.add_widget(self._ip) Clock.schedule_interval(self._update_fps, 2) layout.add_widget(self._toggle) layout.add_widget(self._logo) # layout.add_widget(self._roi_tracker) self._is_updating = False return layout
class DraggableImage(BoxLayout): def __init__(self, source, **kwargs): super().__init__(**kwargs) """ Hierarchy """ self.image = Image(source=source, pos_hint={ "center_x": 0.5, "center_y": 0.5 }) self.container = Scatter() self.container.add_widget(self.image) self.add_widget(self.container) """ Class properties """ self.source = source self.scale_value = 1.0 self.initial_alpha = self.image.color[3] self.initial_pos = None self.debug = False self.clickable = True self.touched = False self.mouse_pos = tuple() # mouse position (frequently updated) """ Some updates per drawing """ Window.bind(mouse_pos=lambda w, p: setattr(self, 'mouse_pos', p)) Window.bind(on_draw=self.fit_image) Window.bind(on_dropfile=self._on_file_drop) def fit_image(self, *args): self.image.size = self.size def _on_file_drop(self, window, file_path): print("Dropping file ...") if self.collide_point(*self.mouse_pos): filePath = file_path.decode("utf-8") if self.debug: print(file_path) self.image.source = filePath self.image.reload() self.source = filePath def on_touch_move(self, touch): if touch.button == "left" and self.clickable: """ Call scatter method """ self.container.on_touch_move(touch) self.clickable = True """ Change image to "moving" state """ self.image.color[3] = self.initial_alpha / 2 self.image.reload() else: self.clickable = False def on_touch_up(self, touch): if self.initial_pos is None: self.initial_pos = self.pos if touch.button == "left": """ Call scatter method """ self.container.on_touch_up(touch) self.clickable = True """ Change image/scatter to normal state """ scale_matrix = Matrix().scale(1.0 / self.container.scale, 1.0 / self.container.scale, 1.0 / self.container.scale) self.container.apply_transform(scale_matrix) self.image.color[3] = self.initial_alpha self.image.reload() # TODO: error when resizing window self.container.pos = self.initial_pos def on_touch_down(self, touch): if self.initial_pos is None: self.initial_pos = self.pos touch.double_tap_time = 1 if touch.is_double_tap and self.collide_point(*touch.pos): self.container.on_touch_down(touch) popup = ImagePopup(source=self.image.source) popup.open() return if touch.button == "left" and self.collide_point(*touch.pos): self.container.on_touch_down(touch) print("Touch ", self) """ Change image to "clicked" state """ scale_matrix = Matrix().scale(self.scale_value, self.scale_value, self.scale_value) self.container.apply_transform(scale_matrix) self.container.center = self.mouse_pos # Fix the image to the position of the mouse def reload_image(self, source): self.image.source = source self.image.reload() def __eq__(self, other): return self is other