class VideoModeWindow(object): def __init__(self, window, main_ui): self.main_ui = main_ui self.window = window # init image translator self.image_translator = ImageTranslate() self.image_translator.start() self.images = OutputImagesStructure() self.video = None self.video_frame = None self.video_frame_index = 0 self.video_frames = 0 # init signal and slot self.init_signal() # send method self.sendMethod = None # timer self.timer = QTimer(self.window) self.timer.setTimerType( 0) # Precise timers try to keep millisecond accuracy self.timer.timeout.connect(self.videoSendProcess) def init_signal(self): # connect signal and slot # tab widget self.main_ui.tabWidget.currentChanged.connect(self.tab_changed) # Threshold value self.main_ui.spinBox_videoBWThreshold.valueChanged['int'].connect( self.main_ui.horizontalSlider_videoBWThreshold.setValue) self.main_ui.horizontalSlider_videoBWThreshold.valueChanged[ 'int'].connect(self.main_ui.spinBox_videoBWThreshold.setValue) self.videoBWThresholdValue = 127 self.main_ui.spinBox_videoBWThreshold.valueChanged.connect( self.videoBWThresholdValueUpdate) self.videoPreviewBWSize = '2X' self.main_ui.checkBox_videoPreviewBW2x.clicked.connect( self.previewBWSizeUpdate) # import image self.main_ui.pbt_videoOpenFile.clicked.connect(self.openVideo) self.lastFolderPath = '' # BM invert self.main_ui.checkBox_videoBWInvert.clicked.connect( self.BWInvertUpdate) self.videoBWInvert = False # preview mode self.main_ui.radioButton_videoPreviewRaw.clicked.connect( self.previewModeUpdate) self.main_ui.radioButton_videoPreviewGray.clicked.connect( self.previewModeUpdate) self.main_ui.radioButton_videoPreviewBW.clicked.connect( self.previewModeUpdate) self.previewMode = 'raw' self.main_ui.horizontalSlider_videoPreviewFrameOffset.valueChanged.connect( self.previewSilderUpdate) self.main_ui.horizontalSlider_videoPreviewFrameOffset.valueChanged[ 'int'].connect(self.main_ui.spinBox_videoFrameOffset.setValue) self.main_ui.spinBox_videoFrameOffset.valueChanged['int'].connect( self.main_ui.horizontalSlider_videoPreviewFrameOffset.setValue) # send to OLED self.main_ui.pbt_videoStartSending.clicked.connect( self.videoSendStateUpdate) self.videoSendFramerate = 1 self.videoSending = False # disable widget before import video file self.setPreviewSliderAndSpinboxEnable(False) self.setVideoWidgetEnable(False) # init tab and install image mode callback for image translator self.tab_changed() """ There only one image translator instance, so we must install the current callback when mode is changed. """ def tab_changed(self): index = self.main_ui.tabWidget.currentIndex() tab_name = self.main_ui.tabWidget.tabText(index) print(tab_name) if tab_name == 'Video': self.image_translator.output_clean() self.image_translator.install_complete_callback( self.image_translate_complete) def setPreviewSliderAndSpinboxEnable(self, enable): self.main_ui.horizontalSlider_videoPreviewFrameOffset.setEnabled( enable) self.main_ui.spinBox_videoFrameOffset.setEnabled(enable) self.main_ui.spinBox_videoSendFramerate.setEnabled(enable) def setVideoWidgetEnable(self, enable): self.main_ui.spinBox_videoBWThreshold.setEnabled(enable) self.main_ui.horizontalSlider_videoBWThreshold.setEnabled(enable) self.main_ui.checkBox_videoBWInvert.setEnabled(enable) self.main_ui.checkBox_videoPreviewBW2x.setEnabled(enable) self.main_ui.radioButton_videoPreviewRaw.setEnabled(enable) self.main_ui.radioButton_videoPreviewGray.setEnabled(enable) self.main_ui.radioButton_videoPreviewBW.setEnabled(enable) self.main_ui.pbt_videoStartSending.setEnabled(enable) def openVideo(self): filename, filetype = QFileDialog.getOpenFileName( self.window, 'Select a video file', self.lastFolderPath) if filename != '': self.lastFolderPath = path.dirname(filename) self.main_ui.lineEdit_videoFileName.setText(filename) # self.video.open(filename) self.video = cv.VideoCapture(filename) # get video info fps = int(self.video.get(cv.CAP_PROP_FPS)) self.video_frames = int(self.video.get(cv.CAP_PROP_FRAME_COUNT)) # update ui self.main_ui.lineEdit_videoInfoFramerate.setText('%d' % fps) self.main_ui.lineEdit_videoInfoDuration.setText( '%d|%.1f' % (self.video_frames, self.video_frames / fps)) self.main_ui.horizontalSlider_videoPreviewFrameOffset.setMinimum(0) self.main_ui.horizontalSlider_videoPreviewFrameOffset.setMaximum( self.video_frames - 1) self.main_ui.spinBox_videoFrameOffset.setMinimum(0) self.main_ui.spinBox_videoFrameOffset.setMaximum( self.video_frames - 1) self.main_ui.horizontalSlider_videoPreviewFrameOffset.setSliderPosition( 0) self.setPreviewSliderAndSpinboxEnable(True) self.setVideoWidgetEnable(True) # translate first frame ret, self.video_frame = self.video.read() h, w, n = self.video_frame.shape k = w / h height = self.main_ui.label_videoPreviewWindow.height() width = int(k * height) - 1 self.image_translator.set_preview_size(width, height) self.image_translator.input_image(self.video_frame) def videoBWThresholdValueUpdate(self): threshold = self.main_ui.spinBox_videoBWThreshold.value() self.image_translator.set_threshold(threshold) if not self.videoSending: self.image_translator.input_image(self.video_frame) def previewBWSizeUpdate(self): if self.main_ui.checkBox_videoPreviewBW2x.isChecked(): self.videoPreviewBWSize = '2X' else: self.videoPreviewBWSize = '1X' self.updateBWPreview() def BWInvertUpdate(self): if self.main_ui.checkBox_videoBWInvert.isChecked(): self.image_translator.set_invert(True) else: self.image_translator.set_invert(False) if not self.videoSending: self.image_translator.input_image(self.video_frame) def previewModeUpdate(self): if self.main_ui.radioButton_videoPreviewRaw.isChecked(): self.previewMode = 'raw' elif self.main_ui.radioButton_videoPreviewGray.isChecked(): self.previewMode = 'gray' else: self.previewMode = 'BW' self.updatePreview() def previewSilderUpdate(self): if self.videoSending: return None # get current slider value index = self.main_ui.horizontalSlider_videoPreviewFrameOffset.value() # read frame specified self.video.set(cv.CAP_PROP_POS_FRAMES, index) ret, self.video_frame = self.video.read() self.image_translator.input_image(self.video_frame) def updatePreview(self): # update preview if self.previewMode == 'raw': image = self.images.raw elif self.previewMode == 'gray': image = self.images.gray else: image = self.images.bw image_pix = OpenCVImage2QPixMap(image) self.main_ui.label_videoPreviewWindow.setPixmap( QPixmap.fromImage(image_pix)) def updateBWPreview(self): if self.videoPreviewBWSize == '2X': image = self.images.output_bw2x else: image = self.images.output_bw image_pix = OpenCVImage2QPixMap(image) self.main_ui.label_videoPreviewOutputBW.setPixmap( QPixmap.fromImage(image_pix)) def videoSendStateUpdate(self): if self.videoSending: self.videoSending = False self.setPreviewSliderAndSpinboxEnable(True) self.main_ui.pbt_videoStartSending.setText('Start Sending') self.timer.stop() self.image_translator.output_clean() else: self.videoSending = True self.setPreviewSliderAndSpinboxEnable(False) self.main_ui.pbt_videoStartSending.setText('Stop Sending') fps = self.main_ui.spinBox_videoSendFramerate.value() self.timer.start(int(1000 / fps)) def videoSendProcess(self): # read next frame ret, self.video_frame = self.video.read() self.image_translator.input_image(self.video_frame) # update last frame self.updatePreview() self.updateBWPreview() # send to serial self.send(self.images.bytes) # update frame index ui index = int(self.video.get(cv.CAP_PROP_POS_FRAMES)) self.main_ui.spinBox_videoFrameOffset.setValue(index) # check if video reach the end if index >= self.video_frames - 1: self.videoSendStateUpdate() def image_translate_complete(self, images_queue): count = images_queue.qsize() for i in range(count): self.images = images_queue.get() # self.images = images_queue.get() if not self.videoSending: self.updatePreview() self.updateBWPreview() def addSendMethod(self, sendMethod): self.sendMethod = sendMethod def send(self, data): if self.sendMethod != None: self.sendMethod.send(data) def exit(self): pass
class ImageModeWindow(object): def __init__(self, window, main_ui): self.main_ui = main_ui self.window = window # export window self.export_window = QWidget() self.init_export_window(self.export_window) # init image translator self.image_translator = ImageTranslate() self.image_translator.start() self.images = OutputImagesStructure() # init signal and slot self.init_signal() self.sendMethod = None def init_export_window(self, window): self.imageExport_ui = Ui_imageExportWindow() self.imageExport_ui.setupUi(window) self.imageExport_ui.retranslateUi(window) def init_signal(self): # connect signal and slot # tab widget self.main_ui.tabWidget.currentChanged.connect(self.tab_changed) # Threshold value self.main_ui.spinBox_BWThreshold.valueChanged['int'].connect(self.main_ui.horizontalSlider_BWThreshold.setValue) self.main_ui.horizontalSlider_BWThreshold.valueChanged['int'].connect(self.main_ui.spinBox_BWThreshold.setValue) self.main_ui.horizontalSlider_BWThreshold.valueChanged.connect(self.BWThresholdValueUpdate) self.previewBWSize = '2X' self.main_ui.checkBox_previewBW2x.clicked.connect(self.previewBWSizeUpdate) # import image self.main_ui.pbt_openImageFile.clicked.connect(self.openImage) self.lastFolderPath = '' # BM invert self.main_ui.checkBox_BWInvert.clicked.connect(self.BWInvertUpdate) self.BWInvert = False # preview mode self.main_ui.radioButton_previewRaw.clicked.connect(self.previewModeUpdate) self.main_ui.radioButton_previewGray.clicked.connect(self.previewModeUpdate) self.main_ui.radioButton_previewBW.clicked.connect(self.previewModeUpdate) self.previewMode = 'raw' # export mode self.main_ui.radioButton_exportHexCArray.clicked.connect(self.exportModeUpdate) self.main_ui.radioButton_exportHexValue.clicked.connect(self.exportModeUpdate) self.exportMode = 'HexCArray' self.main_ui.pbt_exportImage.clicked.connect(self.exportImage) # send to OLED self.main_ui.radioButton_SendImageAuto.clicked.connect(self.imageSendModeUpdate) self.main_ui.radioButton_sendImageManually.clicked.connect(self.imageSendModeUpdate) self.imageSendMode = 'Manually' self.main_ui.pbt_sendImage.clicked.connect(self.sendManually) # disable self.setImageWidgetEnable(False) # init tab and install image mode callback for image translator self.tab_changed() """ There only one image translator instance, so we must install the current callback when mode is changed. """ def tab_changed(self): index = self.main_ui.tabWidget.currentIndex() tab_name = self.main_ui.tabWidget.tabText(index) if tab_name == 'Image': self.image_translator.output_clean() self.image_translator.install_complete_callback(self.image_translate_complete) def setImageWidgetEnable(self, enable): self.main_ui.radioButton_previewRaw.setEnabled(enable) self.main_ui.radioButton_previewGray.setEnabled(enable) self.main_ui.radioButton_previewBW.setEnabled(enable) self.main_ui.spinBox_BWThreshold.setEnabled(enable) self.main_ui.horizontalSlider_BWThreshold.setEnabled(enable) self.main_ui.checkBox_BWInvert.setEnabled(enable) self.main_ui.checkBox_previewBW2x.setEnabled(enable) self.main_ui.pbt_exportImage.setEnabled(enable) self.main_ui.radioButton_SendImageAuto.setEnabled(enable) self.main_ui.pbt_sendImage.setEnabled(enable) def openImage(self): filename, filetype = QFileDialog.getOpenFileName(self.window, 'Select a image file', self.lastFolderPath) if filename != '': self.lastFolderPath = path.dirname(filename) self.main_ui.lineEdit_imageFileName.setText(filename) self.image_raw = cv.imread(filename) self.setImageWidgetEnable(True) h, w, n = self.image_raw.shape k = w / h height = self.main_ui.label_previewWindow.height() width = int(k * height) - 1 self.image_translator.set_preview_size(width, height) self.image_translator.input_image(self.image_raw) def imageSendModeUpdate(self): if self.main_ui.radioButton_sendImageManually.isChecked(): self.imageSendMode = 'Manually' else: self.imageSendMode = 'Auto' def BWThresholdValueUpdate(self): thresholdValue = self.main_ui.spinBox_BWThreshold.value() self.image_translator.set_threshold(thresholdValue) self.image_translator.input_image(self.image_raw) def previewBWSizeUpdate(self): if self.main_ui.checkBox_previewBW2x.isChecked(): self.previewBWSize = '2X' else: self.previewBWSize = '1X' self.updateBWPreview() def exportModeUpdate(self): if self.main_ui.radioButton_exportHexCArray.isChecked(): self.exportMode = 'HexCArray' else: self.exportMode = 'HexValue' def exportImage(self): image_bytes = self.images.bytes # export out_str = '' if self.exportMode == 'HexCArray': out_str += 'uint8_t bitmap[] = {\n' out_hex_nums = ['0x%02x' % x for x in image_bytes] numbers_per_line = 32 for i in range(int(1024 / numbers_per_line)): index = i * numbers_per_line out_str += ' %s,\n' % (', '.join(out_hex_nums[index:(index + numbers_per_line)])) out_str += '};\n' else: out_hex_nums = ['%02x' % x for x in image_bytes] out_str += ' '.join(out_hex_nums) self.imageExport_ui.textEdit_eportEditor.setText(out_str) self.export_window.show() def BWInvertUpdate(self): if self.main_ui.checkBox_BWInvert.isChecked(): self.BWInvert = True else: self.BWInvert = False self.image_translator.set_invert(self.BWInvert) self.image_translator.input_image(self.image_raw) def previewModeUpdate(self): if self.main_ui.radioButton_previewRaw.isChecked(): self.previewMode = 'raw' elif self.main_ui.radioButton_previewGray.isChecked(): self.previewMode = 'gray' else: self.previewMode = 'bw' self.updatePreview() def updatePreview(self): # update preview if self.previewMode == 'raw': image = self.images.raw elif self.previewMode == 'gray': image = self.images.gray else: image = self.images.bw image_pix = OpenCVImage2QPixMap(image) self.main_ui.label_previewWindow.setPixmap(QPixmap.fromImage(image_pix)) def updateBWPreview(self): # update BW preview if self.previewBWSize == '2X': image = self.images.output_bw2x else: image = self.images.output_bw image_pix = OpenCVImage2QPixMap(image) self.main_ui.label_previewOutputBW.setPixmap(QPixmap.fromImage(image_pix)) # send to display if self.imageSendMode == 'Auto': self.send(self.images.bytes) def sendManually(self): self.send(self.images.bytes) def addSendMethod(self, sendMethod): self.sendMethod = sendMethod def image_translate_complete(self, images_queue): count = images_queue.qsize() for i in range(count): self.images = images_queue.get() self.updatePreview() self.updateBWPreview() def send(self, data): if self.sendMethod != None: self.sendMethod.send(data) def exit(self): pass
class ScreenModeWindow(object): def __init__(self, window, main_ui): self.main_ui = main_ui self.window = window # sample window self.sample_window = ScreenSampleWindow() self.sample_window.setWindowOpacity(0.01) self.sample_window.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) self.sample_window.resize(800, 600) # init image translator self.image_translator = ImageTranslate() self.images = OutputImagesStructure() self.screen_image = None h = self.main_ui.label_screenPreviewWindow.height() w = self.main_ui.label_screenPreviewWindow.width() self.image_translator.set_preview_size(w, h) self.image_translator.start() # init signal and slot self.init_signal() # serial send method self.sendMethod = None # timer self.drawRectTimer = QTimer(self.window) self.drawRectTimer.setTimerType(0) self.drawRectTimer.timeout.connect(self.sampleWindowUpdate) self.screenShotTimer = QTimer(self.window) self.screenShotTimer.setTimerType(0) self.screenShotTimer.timeout.connect(self.screenImageGet) def init_signal(self): # connect signal and slot # tab widget self.main_ui.tabWidget.currentChanged.connect(self.tab_changed) # pop sample button self.main_ui.pbt_screenSampleWindow.clicked.connect(self.openSampleWindow) self.main_ui.checkBox_sampleWindowShowOnTop.clicked.connect(self.sampleWindowShowMode) # Threshold value self.main_ui.spinBox_screenBWThreshold.valueChanged['int'].connect(self.main_ui.horizontalSlider_screenBWThreshold.setValue) self.main_ui.horizontalSlider_screenBWThreshold.valueChanged['int'].connect(self.main_ui.spinBox_screenBWThreshold.setValue) self.videoBWThresholdValue = 127 self.main_ui.spinBox_screenBWThreshold.valueChanged.connect(self.BWThresholdValueUpdate) self.previewBWSize = '2X' self.main_ui.checkBox_screenPreviewBW2x.clicked.connect(self.previewBWSizeUpdate) # BM invert self.main_ui.checkBox_screenBWInvert.clicked.connect(self.BWInvertUpdate) self.screenBWInvert = False # preview mode self.main_ui.radioButton_screenPreviewRaw.clicked.connect(self.previewModeUpdate) self.main_ui.radioButton_screenPreviewGray.clicked.connect(self.previewModeUpdate) self.main_ui.radioButton_screenPreviewBW.clicked.connect(self.previewModeUpdate) self.previewMode = 'raw' # send frame signal self.main_ui.pbt_screenStartSending.clicked.connect(self.sendModeUpdate) self.screenSending = False self.setScreenWidgetEnable(False) # init tab and install image mode callback for image translator self.tab_changed() """ There only one image translator instance, so we must install the current callback when mode is changed. """ def tab_changed(self): index = self.main_ui.tabWidget.currentIndex() tab_name = self.main_ui.tabWidget.tabText(index) print(tab_name) if tab_name == 'Screen': self.image_translator.output_clean() self.image_translator.install_complete_callback(self.image_translate_complete) def setScreenWidgetEnable(self, enable): self.main_ui.spinBox_screenBWThreshold.setEnabled(enable) self.main_ui.horizontalSlider_screenBWThreshold.setEnabled(enable) self.main_ui.checkBox_screenBWInvert.setEnabled(enable) self.main_ui.checkBox_screenPreviewBW2x.setEnabled(enable) self.main_ui.radioButton_screenPreviewRaw.setEnabled(enable) self.main_ui.radioButton_screenPreviewGray.setEnabled(enable) self.main_ui.radioButton_screenPreviewBW.setEnabled(enable) self.main_ui.pbt_screenStartSending.setEnabled(enable) if enable == True: self.main_ui.pbt_screenSampleWindow.setText('Close Sample Window') else: self.main_ui.pbt_screenSampleWindow.setText('Open Sample Window') def openSampleWindow(self): if self.sample_window.isHidden(): self.setScreenWidgetEnable(True) self.main_ui.checkBox_sampleWindowShowOnTop.setEnabled(False) self.sample_window.show() self.drawRectTimer.start(30) self.screenShotTimer.start(10) else: self.setScreenWidgetEnable(False) self.main_ui.checkBox_sampleWindowShowOnTop.setEnabled(True) if self.screenSending: self.sendModeUpdate() self.sample_window.hide() self.drawRectTimer.stop() self.screenShotTimer.stop() def sampleWindowShowMode(self): if self.main_ui.checkBox_sampleWindowShowOnTop.isChecked(): self.sample_window.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) else: self.sample_window.setWindowFlags(QtCore.Qt.Widget) def sampleWindowUpdate(self): if self.sample_window.isHidden(): self.drawRectTimer.stop() return None self.sample_window.draw_rect() def screenImageGet(self): self.screen_image = self.sample_window.get_window_image() self.image_translator.input_image(self.screen_image) if self.screenSending: self.updatePreview() self.updateBWPreview() self.send(self.images.bytes) def BWThresholdValueUpdate(self): threshold = self.main_ui.spinBox_screenBWThreshold.value() self.image_translator.set_threshold(threshold) if not self.screenSending: self.image_translator.input_image(self.screen_image) def previewBWSizeUpdate(self): if self.main_ui.checkBox_screenPreviewBW2x.isChecked(): self.previewBWSize = '2X' else: self.previewBWSize = '1X' self.updateBWPreview() def BWInvertUpdate(self): if self.main_ui.checkBox_screenBWInvert.isChecked(): self.image_translator.set_invert(True) else: self.image_translator.set_invert(False) if not self.screenSending: self.image_translator.input_image(self.screen_image) def previewModeUpdate(self): if self.main_ui.radioButton_screenPreviewRaw.isChecked(): self.previewMode = 'raw' elif self.main_ui.radioButton_screenPreviewGray.isChecked(): self.previewMode = 'gray' else: self.previewMode = 'bw' self.updatePreview() def updatePreview(self): # update preview if self.previewMode == 'raw': image = self.images.raw elif self.previewMode == 'gray': image = self.images.gray else: image = self.images.bw image_pix = OpenCVImage2QPixMap(image) self.main_ui.label_screenPreviewWindow.setPixmap(QPixmap.fromImage(image_pix)) def updateBWPreview(self): if self.previewBWSize == '2X': image = self.images.output_bw2x else: image = self.images.output_bw image_pix = OpenCVImage2QPixMap(image) self.main_ui.label_screenPreviewOutputBW.setPixmap(QPixmap.fromImage(image_pix)) def image_translate_complete(self, images_queue): count = images_queue.qsize() for i in range(count): self.images = images_queue.get() if not self.screenSending: self.updatePreview() self.updateBWPreview() def sendModeUpdate(self): if self.screenSending: self.screenSending = False self.main_ui.pbt_screenStartSending.setText('Start Sending') self.screenShotTimer.setInterval(10) else: self.screenSending = True self.main_ui.pbt_screenStartSending.setText('Stop Sending') fps = self.main_ui.spinBox_screenSendFramerate.value() self.screenShotTimer.setInterval(int(1000/fps)) def addSendMethod(self, sendMethod): self.sendMethod = sendMethod def send(self, data): if self.sendMethod != None: self.sendMethod.send(data) def exit(self): # self.sample_window.close() # self.sample_window.destroy() self.screenShotTimer.stop() self.drawRectTimer.stop()