def onchange_miniature_selection(self, emitter, selected, miniature): print(selected) if selected: self.miniature_selection_list.append(miniature) else: self.miniature_selection_list.remove(miniature) if len(self.miniature_selection_list) > 1: print("stitching %s images"%len(self.miniature_selection_list)) result = self.miniature_selection_list[0].image.img.copy() roi_logo_x = gui.from_pix(self.roi_logo_widget.style['left']) roi_logo_w = gui.from_pix(self.roi_logo_widget.style['width']) t = time.time() w = float(self.spin_horizontal_perspective.get_value()) h = float(self.spin_vertical_perspective.get_value()) #result = self.calibrate_image(result) result = image_utils.perspective_correction(result, w, h) for m in self.miniature_selection_list[1:]: img = m.image.img#self.calibrate_image(m.image.img) img = image_utils.perspective_correction(img, w, h) result = image_utils.stitch_fast(result, img, roi_logo_x, roi_logo_x+roi_logo_w, 30.0) #image_utils.stitch(result, m.image.img, 20.0) print(time.time() - t) self.camera_image.refresh(result)
def onclick_perspective_correction(self, emitter=None): w = float(self.spin_horizontal_perspective.get_value()) h = float(self.spin_vertical_perspective.get_value()) self.shelve['spin_horizontal_perspective'] = w self.shelve['spin_vertical_perspective'] = h #test #self.camera_image.set_image("./test.bmp") result = image_utils.perspective_correction(self.camera_image.img, w, h) self.camera_image.refresh(result)
def live_video_thread(app, camera, perspective_correction_value_horiz, perspective_correction_value_vert): app.process_thread_stop_flag = False images_buffer = None while not app.process_thread_stop_flag: images_buffer = camera.get_image_buf() if not images_buffer is None: print("Thread loop - Immagini da giuntare: %s"%len(images_buffer)) app.show_process_image(images_buffer[0][1]) continue for t,img in images_buffer[1:]: #img = image_utils.histogram_equalize(img) #img = app.calibrate_image(img) img = image_utils.perspective_correction(img, perspective_correction_value_horiz, perspective_correction_value_vert) app.show_process_image(img)
def process_thread(app, camera, img_logo, stitch_minimum_overlap, perspective_correction_value_horiz, perspective_correction_value_vert): """ PRECONDIZIONE: - NASTRO IN MOVIMENTO Prima fase di individuazione logo Misura lunghezza Prendi immagini ad ogni stitch (tramite l'intera larghezza immagine) seziona l'intera immagine in fasce orizzontali cerca tutte le occorrenze di queste fasce tramite match_template_all se almeno 2 risultati abbiamo H logo Eventuale misura orizzontale logo, per individuare migliore zona di template matching al fine velocizzare di stitching Vedere tramite filtro verticale dove l'immagine cambia, dovrebbero essere individuabili N fasce verticali quanti sono i loghi memorizzare aree e usarle per template matching Seconda fase Scegliere un'immagine qualsiasi da usare come target iniziale centraggio immagine, poi l'operatore può muovere in alto o in basso per centrare il logo Terza fase Stitching immagini Correggere prospettiva Tentare stitch, se fallisce allora stitchare in base a spostamento medio Se immagine stitch piu grande di logoX2 allora trovare l'immagine target iniziale e mostrare lo stitch centato al target Ad ogni successivo stitch, eliminare eccesso H immagine che supera logoX2 """ app.process_thread_stop_flag = False #caricamento files di test """ images_buffer = [] image_files = glob.glob('./immagini_processo/frames/*.jpg') for img in image_files: img = cv2.imread(img, cv2.IMREAD_COLOR) images_buffer.append([time.time(), img]) """ images_buffer = None print("FASE 1") t = time.time() print("controllo numero immagini sufficienti") while app.process_thread_stop_flag==False and (time.time()-t)<5: if images_buffer!=None: if len(images_buffer)>3: break time.sleep(0.5) images_buffer = camera.get_image_buf() print(images_buffer) #creiamo scia loghi, in modo da individuare le aree occupate da ogni logo #img = image_utils.perspective_correction(images_buffer[0][1], perspective_correction_value_horiz, perspective_correction_value_vert) prev_thresh = image_utils.threshold(images_buffer[0][1]) diff_images = prev_thresh.copy()#image_utils.threshold(images_buffer[0][1])#np.zeros((img.shape[1], img.shape[0]),np.uint8) diff_images[:] = 0 kernel = np.ones((2,2),np.uint8) for t,img in images_buffer[:]: #comando stop operatore if app.process_thread_stop_flag: return #img = image_utils.perspective_correction(img, perspective_correction_value_horiz, perspective_correction_value_vert) img_thresh = image_utils.threshold(img) del img img_thresh = cv2.dilate(img_thresh,kernel,iterations = 1) diff_images = cv2.bitwise_or(diff_images, cv2.bitwise_xor(prev_thresh, img_thresh)) prev_thresh = img_thresh diff_images = cv2.erode(diff_images,kernel,iterations = 1) diff_images = image_utils.perspective_correction(diff_images, perspective_correction_value_horiz, perspective_correction_value_vert) app.add_miniature(diff_images, "diff_images.png") """params = cv2.SimpleBlobDetector_Params() params.filterByCircularity = False params.filterByConvexity = False params.filterByInertia = False # I loghi appaiono di colore bianco params.minThreshold = 100 # the graylevel of images params.maxThreshold = 255 params.filterByColor = False #params.blobColor = 255 # Filter by Area params.filterByArea = True params.minArea = 20 detector = cv2.SimpleBlobDetector_create(params) #SimpleBlobDetector() # Detect blobs. keypoints = detector.detect(diff_images.astype(np.uint8)) for k in keypoints: cv2.circle(img, (int(k.pt[0]), int(k.pt[1])), 20, (255,0,0), 5) """ connectivity=1 num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(diff_images , connectivity , cv2.CV_32S) lblareas = stats[:,cv2.CC_STAT_AREA] if len(stats) < 3: app.process_thread_stop_flag = True return ordered_regions_area = sorted(enumerate(lblareas), key=(lambda x: x[1]), reverse=True) #(index, area) print("ordered regions area %s"%str(ordered_regions_area)) imax = ordered_regions_area[2][0] #1 skip the background indexed as 0 #print("imax %s"%str(imax)) #print(stats[imax]) x1, y1, x2, y2 = (stats[imax, cv2.CC_STAT_LEFT], stats[imax, cv2.CC_STAT_TOP], stats[imax, cv2.CC_STAT_WIDTH]+stats[imax, cv2.CC_STAT_LEFT], stats[imax, cv2.CC_STAT_HEIGHT]+stats[imax, cv2.CC_STAT_TOP]) img = image_utils.perspective_correction(images_buffer[0][1], perspective_correction_value_horiz, perspective_correction_value_vert) cv2.rectangle(img, (x1, y1), (x2, y2), (0,255,0), 3) app.roi_logo_widget.style['left'] = gui.to_pix(x1) app.roi_logo_widget.style['top'] = gui.to_pix(y1) app.roi_logo_widget.style['width'] = gui.to_pix(x2-x1) app.roi_logo_widget.style['height'] = gui.to_pix(y2-y1) """ imax = ordered_regions_area[2][0] x1, y1, x2, y2 = (stats[imax, cv2.CC_STAT_LEFT], stats[imax, cv2.CC_STAT_TOP], stats[imax, cv2.CC_STAT_WIDTH]+stats[imax, cv2.CC_STAT_LEFT], stats[imax, cv2.CC_STAT_HEIGHT]+stats[imax, cv2.CC_STAT_TOP]) cv2.rectangle(img, (x1, y1), (x2, y2), (255,0,0), 3) imax = ordered_regions_area[3][0] x1, y1, x2, y2 = (stats[imax, cv2.CC_STAT_LEFT], stats[imax, cv2.CC_STAT_TOP], stats[imax, cv2.CC_STAT_WIDTH]+stats[imax, cv2.CC_STAT_LEFT], stats[imax, cv2.CC_STAT_HEIGHT]+stats[imax, cv2.CC_STAT_TOP]) cv2.rectangle(img, (x1, y1), (x2, y2), (0,0,255), 3) """ app.add_miniature(img, "loghi.png") #return roi_logo_x1 = x1 roi_logo_x2 = x2 vel_nastro = 0.0 #velocita' nastro utilizzata per lo stitching in caso di mancato pattern matching mem_t = 0 #tempo immagine precedente immagine_nastro = None vel_nastro_array = [] similarity_array = [] while not app.process_thread_stop_flag: #try: if True: images_buffer = camera.get_image_buf() """ print("attenzione, salvataggio immagini da disabilitare !!!") for t,img in images_buffer[:]: filename = "%s.png"%str(time.time()) cv2.imwrite("./immagini_processo/test/" + filename, img) """ if not images_buffer is None: print("Thread loop - Immagini da giuntare: %s"%len(images_buffer)) mem_t, img = images_buffer[0] immagine_nastro = image_utils.perspective_correction(img, perspective_correction_value_horiz, perspective_correction_value_vert) mem_image = img for t,img in images_buffer[1:]: #img = image_utils.histogram_equalize(img) #img = app.calibrate_image(img) img = image_utils.perspective_correction(img, perspective_correction_value_horiz, perspective_correction_value_vert) """ if offset_y==-1: ok, _off_y, similarity_result = image_utils.find_stitch_offset(img, immagine_nastro, roi_logo_x, roi_logo_w) if ok: offset_y=_off_y else: immagine_nastro = img.copy() index = 1 continue #forse invertire le immagini top e bottom #immagine_nastro = image_utils.stitch_fast(immagine_nastro, img, roi_logo_x, roi_logo_w) immagine_nastro = image_utils.stitch_offset(img, immagine_nastro, offset_y*index) index = index + 1 """ #immagine_nastro = image_utils.stitch_fast(img, immagine_nastro, roi_logo_x, roi_logo_w) ok, offset_y, similarity_result = image_utils.find_stitch_offset(img, mem_image, roi_logo_x1, roi_logo_x2, 30) similarity_array.insert(0, similarity_result) similarity_array = similarity_array[:30] #print("--------mean similarity: %s"%np.mean(similarity_array)) if len(similarity_array)<3 or similarity_result<np.mean(similarity_array): #ok #print("offset y: %s"%offset_y) immagine_nastro = image_utils.stitch_offset(img, immagine_nastro, offset_y) #dato che il matching e' andato a buon fine, determiniamo la vel_nastro # in modo che se il prossimo matching non va' bene, stitchiamo in base a velocita' vel_nastro_array.insert(0,float(offset_y)/(t-mem_t + 0.00000000001)) #sommo un numero molto piccolo per evitare DIV 0, e risparmiare un if vel_nastro_array=vel_nastro_array[:30] mem_t = t else: try: #continue #stitch by previous offset_y relative to speed offset_y = int(np.mean(vel_nastro_array) * (t-mem_t)) #print(">>>>> vel nastro: %s offset y: %s"%(np.mean(vel_nastro_array), offset_y)) immagine_nastro = image_utils.stitch_offset(img, immagine_nastro, offset_y) mem_t = t except Exception as e: print("Errore giunzione immagini a velocita'. offset_y:%s - err:%s"%(offset_y,e)) h = int(app.spin_h_logo.get_value()) if not immagine_nastro is None: if immagine_nastro.shape[0]>h: break mem_image = img if not immagine_nastro is None: app.show_process_image(immagine_nastro) #h = int(app.spin_h_logo.get_value()) #andrebbe determinato h logo #l'ultima immagine la rendo disponibile per il prossimo stitching #img = image_utils.perspective_correction(img, perspective_correction_value_horiz, perspective_correction_value_vert) #immagine_nastro = images_buffer[-1][1]#immagine_nastro[0:h,:] #pulisco l'immagine per il successivo ciclo immagine_nastro = None
def image_overprint_thread(app, camera, perspective_correction_value_horiz, perspective_correction_value_vert): """ Si prende un'immagine tutte le successive immagini vengono matchate unite e sovrapposte a questa """ app.process_thread_stop_flag = False images_buffer = None immagine_nastro = None vel_nastro_array = [] similarity_array = [] while not app.process_thread_stop_flag: try: images_buffer = camera.get_image_buf() """ print("attenzione, salvataggio immagini da disabilitare !!!") for t,img in images_buffer[:]: filename = "%s.png"%str(time.time()) cv2.imwrite("./immagini_processo/test/" + filename, img) """ if not images_buffer is None: print("Thread loop - Immagini da giuntare: %s"%len(images_buffer)) mem_t, img = images_buffer[0] immagine_nastro = image_utils.perspective_correction(img, perspective_correction_value_horiz, perspective_correction_value_vert) mem_image = img for t,img in images_buffer[1:]: #img = image_utils.histogram_equalize(img) #img = app.calibrate_image(img) #memorizzazione area logo da selezione a video roi_logo_x1 = gui.from_pix(app.selection_area_widget.style['left']) roi_logo_x2 = roi_logo_x1 + gui.from_pix(app.selection_area_widget.style['width']) #tentativo stitching di nuova immagine in immagine_base e viceversa # lo stitching on similarity piu' vicino a 0 (migliore) viene considerato ok, offset_y, similarity_result = image_utils.find_stitch_offset(img, mem_image, roi_logo_x1, roi_logo_x2, 100) ok, offset_y, similarity_result2 = image_utils.find_stitch_offset(mem_image, img, roi_logo_x1, roi_logo_x2, 100) if similarity_result<similarity_result2: #normale stitching di img in immagine nastro (dove Y img risulta piu' in basso) immagine_nastro = image_utils.stitch_offset(img, immagine_nastro, offset_y) else: #stitching contrario immagine nastro in img (dove Y img risulta piu' alto) # ma siccome vogliamo mantenere l'immagine nastro di sfondo, e volendo inoltre mantenere il risultato # allineato in alto (immagine ferma), copiamo img in immagine_nastro, prendendo di img solo la parte che si sovrappone # a immagine_nastro immagine_nastro = image_utils.stitch_offset(img[offset_y:,:], immagine_nastro, offset_y) #ritagliamo il risultato solo in caso la dimensione supera quella impostata sulla spinbox h = int(app.spin_h_logo.get_value()) if immagine_nastro.shape[0] > h: immagine_nastro = immagine_nastro[0:h,:) # 0:mem_image.shape[1]] if not immagine_nastro is None: app.show_process_image(immagine_nastro) #h = int(app.spin_h_logo.get_value()) #andrebbe determinato h logo #l'ultima immagine la rendo disponibile per il prossimo stitching #img = image_utils.perspective_correction(img, perspective_correction_value_horiz, perspective_correction_value_vert) #immagine_nastro = images_buffer[-1][1]#immagine_nastro[0:h,:] #pulisco l'immagine per il successivo ciclo immagine_nastro = None #time.sleep(1.5) except: print("exception")