def __init__(self): self.thread = threading.Thread(target=self.process_threading) self.thread_run = False self.input_queue = queue.Queue() self.output_queue = queue.Queue() self.output_images = OutputImagesStructure() self.complete_callback = None self.image_to_bw = BWImageToBytes() self.update_setting = False self.preview_image_width = 128 self.preview_image_height = 64 self.preview_image_width_temp = 128 self.preview_image_height_temp = 64 self.output_image_width = 128 self.output_image_height = 64 self.output_image_width_temp = 128 self.output_image_height_temp = 64 self.bw_threshold = 127 self.bw_threshold_temp = 127 self.bw_invert = False self.bw_invert_temp = False
def __init__(self): self.thread = threading.Thread(target=self.process_threading) self.thread_run = False self.input_queue = queue.Queue() self.output_queue = queue.Queue() self.output_images = OutputImagesStructure() self.complete_callback = None self.image_to_bw = BWImageToBytes() self.update_setting = False self.preview_image_width = 128 self.preview_image_height = 64 self.preview_image_width_temp = 128 self.preview_image_height_temp = 64 self.output_image_width = 128 self.output_image_height = 64 self.output_image_width_temp = 128 self.output_image_height_temp = 64 self.bw_threshold = 127 self.bw_threshold_temp = 127 self.bw_invert = False self.bw_invert_temp = False self.dither_size = 0 self.dither_size_temp = 0 self.binarization_mode = 'threshold' self.binarization_mode_temp = 'threshold' self.binarization_equalizeHist = False self.binarization_equalizeHist_temp = False # init dll self.dithering = None self.error_diffusion = None self.load_dll()
def __init__(self): # setup window self.window = QMainWindow() self.main_ui = Ui_mainWindow() self.main_ui.setupUi(self.window) self.main_ui.retranslateUi(self.window) self.imageModeWindow = ImageModeWindow(self.window, self.main_ui) self.videoModeWindow = VideoModeWindow(self.window, self.main_ui) self.screenModeWindow = ScreenModeWindow(self.window, self.main_ui) # BW image to bytes instance self.image_to_bw = BWImageToBytes() # image processing self.image_translator = ImageTranslate() self.image_translator.start() self.connectSignal() # show window self.window.show()
class ImageTranslate(object): def __init__(self): self.thread = threading.Thread(target=self.process_threading) self.thread_run = False self.input_queue = queue.Queue() self.output_queue = queue.Queue() self.output_images = OutputImagesStructure() self.complete_callback = None self.image_to_bw = BWImageToBytes() self.update_setting = False self.preview_image_width = 128 self.preview_image_height = 64 self.preview_image_width_temp = 128 self.preview_image_height_temp = 64 self.output_image_width = 128 self.output_image_height = 64 self.output_image_width_temp = 128 self.output_image_height_temp = 64 self.bw_threshold = 127 self.bw_threshold_temp = 127 self.bw_invert = False self.bw_invert_temp = False self.dither_size = 0 self.dither_size_temp = 0 self.dither_enabled = False self.dither_enabled_temp = False def start(self): if self.thread_run: return None self.thread_run = True self.thread.start() def stop(self): self.thread_run = False self.thread.join() def set_threshold(self, value): if value != 0: self.bw_threshold_temp = value self.update_setting = True def set_dither_size(self, size): self.dither_size_temp = size self.update_setting = True def set_dither_enable(self, enable): self.dither_enabled_temp = enable self.update_setting = True def set_invert(self, enable): if type(enable) == bool: self.bw_invert_temp = enable self.update_setting = True def set_preview_size(self, width, height): self.preview_image_width_temp = width self.preview_image_height_temp = height self.update_setting = True def set_output_size(self, width, height): self.output_image_width_temp = width self.output_image_height_temp = height self.update_setting = True def update_parameters(self): if not self.update_setting: return None self.update_setting = False self.bw_threshold = self.bw_threshold_temp self.bw_invert = self.bw_invert_temp self.dither_size = self.dither_size_temp self.dither_enabled = self.dither_enabled_temp self.preview_image_width = self.preview_image_width_temp self.preview_image_height = self.preview_image_height_temp self.output_image_width = self.output_image_width_temp self.output_image_height = self.output_image_height_temp def input_image(self, image): self.input_queue.put(image, timeout=0.1) def output_clean(self): while self.output_queue.qsize() > 0: self.output_queue.get() def read_images(self): try: return self.output_queue.get(timeout=0.1) except: return None def install_complete_callback(self, callback): if callback != None: self.complete_callback = callback def remove_complete_callback(self): self.complete_callback = None def image_translate(self, image): image_raw = cv.resize( image, (self.preview_image_width, self.preview_image_height)) image_gray = cv.cvtColor(image_raw, cv.COLOR_BGR2GRAY) if not self.bw_invert: image_bw = (image_gray > self.bw_threshold) * np.uint8(255) else: image_bw = (image_gray <= self.bw_threshold) * np.uint8(255) image_out_bw2x = cv.resize( image_bw, (2 * self.output_image_width, 2 * self.output_image_height)) if self.dither_enabled: image_gray_1x = cv.resize( image_gray, (self.output_image_width, self.output_image_height)) image_gray_1x = cv.equalizeHist(image_gray_1x) image_out_bw = dither(image_gray_1x, self.dither_size) else: image_out_bw = cv.resize( image_bw, (self.output_image_width, self.output_image_height)) image_out_bw_bytes = self.image_to_bw.convert(image_out_bw) self.output_images.raw = image_raw self.output_images.gray = image_gray self.output_images.bw = image_bw self.output_images.output_bw = image_out_bw self.output_images.output_bw2x = image_out_bw2x self.output_images.bytes = image_out_bw_bytes def output_images_to_queue(self): self.output_queue.put(self.output_images, timeout=0.1) def process_threading(self): while self.thread_run: try: image = self.input_queue.get(timeout=0.1) self.update_parameters() self.image_translate(image) self.output_images_to_queue() if self.complete_callback != None: self.complete_callback(self.output_queue) except: pass
class MainWindow(object): def __init__(self): # setup window self.window = QMainWindow() self.main_ui = Ui_mainWindow() self.main_ui.setupUi(self.window) self.main_ui.retranslateUi(self.window) self.imageModeWindow = ImageModeWindow(self.window, self.main_ui) self.videoModeWindow = VideoModeWindow(self.window, self.main_ui) self.screenModeWindow = ScreenModeWindow(self.window, self.main_ui) # BW image to bytes instance self.image_to_bw = BWImageToBytes() # image processing self.image_translator = ImageTranslate() self.image_translator.start() self.connectSignal() # show window self.window.show() def connectSignal(self): # connect serial port widgets self.main_ui.pbt_scanSerialPort.clicked.connect(self.portScan) self.main_ui.combox_serialPortList.activated.connect(self.portSelect) self.main_ui.pbt_serialOpen.clicked.connect(self.portOpen) self.portOpened = False # connect display setting self.main_ui.spinBox_displayRow.valueChanged.connect(self.displayColumnRowSetting) self.main_ui.spinBox_displayCol.valueChanged.connect(self.displayColumnRowSetting) self.main_ui.checkBox_displayFlipH.clicked.connect(self.displayFlipModeSetting) self.main_ui.checkBox_displayFlipV.clicked.connect(self.displayFlipModeSetting) self.main_ui.comboBox_displayScanDirection.activated.connect(self.displayScanDirectionSetting) self.main_ui.comboBox_displayByteDirection.activated.connect(self.displayByteDirectionSetting) self.main_ui.comboBox_displaySignBit.activated.connect(self.displaySignBitSetting) self.displaySettingInit() # connect binarization setting self.main_ui.radioButton_binarizationThreshold.clicked.connect(self.binarizationSetting) self.main_ui.radioButton_binarizationDither.clicked.connect(self.binarizationSetting) self.main_ui.comboBox_ditherBayerSize.activated.connect(self.binarizationSetting) self.binarizationSetting() def portScan(self): portList = SerialPort.getDeviceList() self.main_ui.combox_serialPortList.clear() for portInfo, port in portList: self.main_ui.combox_serialPortList.addItem(portInfo, port) def portSelect(self): self.port = self.main_ui.combox_serialPortList.currentData() self.baudrate = self.main_ui.spinBox_baudrate.value() def portOpen(self): if self.portOpened == False: try: self.serial = SerialPort(self.port, self.baudrate) self.portOpened = True self.main_ui.pbt_serialOpen.setText('Close') self.imageModeWindow.addSendMethod(self.serial) self.videoModeWindow.addSendMethod(self.serial) self.screenModeWindow.addSendMethod(self.serial) except Exception: print('Serial port open false.') else: try: self.serial.close() self.serial = None self.portOpened = False self.main_ui.pbt_serialOpen.setText('Open') self.imageModeWindow.addSendMethod(None) except Exception: print('Serial port close false.') def binarizationSetting(self): if self.main_ui.radioButton_binarizationThreshold.isChecked(): self.image_translator.set_dither_enable(False) else: self.image_translator.set_dither_enable(True) size_str = self.main_ui.comboBox_ditherBayerSize.currentText() size = int(size_str[:-1]) self.image_translator.set_dither_size(size) def displaySettingInit(self): self.displayColumnRowSetting() self.displayFlipModeSetting() self.displayScanDirectionSetting() self.displayByteDirectionSetting() self.displaySignBitSetting() def displayColumnRowSetting(self): col = self.main_ui.spinBox_displayCol.value() row = self.main_ui.spinBox_displayRow.value() self.image_translator.set_output_size(col, row) def displayFlipModeSetting(self): flip_h = self.main_ui.checkBox_displayFlipH.isChecked() flip_v = self.main_ui.checkBox_displayFlipV.isChecked() self.image_to_bw.setHorizontalFlip(flip_h) self.image_to_bw.setVerticalFlip(flip_v) def displayScanDirectionSetting(self): scan_direction = self.main_ui.comboBox_displayScanDirection.currentText() if scan_direction == 'Horizontal': dir = 'H' else: dir = 'V' self.image_to_bw.setScanDirection(dir) def displayByteDirectionSetting(self): byte_direction = self.main_ui.comboBox_displayByteDirection.currentText() if byte_direction == 'Horizontal': dir = 'H' else: dir = 'V' self.image_to_bw.setByteDirection(dir) def displaySignBitSetting(self): sign_bit = self.main_ui.comboBox_displaySignBit.currentText() self.image_to_bw.setSignBit(sign_bit) def exit(self): if self.portOpened: self.serial.close() self.imageModeWindow.exit() self.videoModeWindow.exit() self.screenModeWindow.exit() self.image_translator.stop()
class ImageTranslate(object): def __init__(self): self.thread = threading.Thread(target=self.process_threading) self.thread_run = False self.input_queue = queue.Queue() self.output_queue = queue.Queue() self.output_images = OutputImagesStructure() self.complete_callback = None self.image_to_bw = BWImageToBytes() self.update_setting = False self.preview_image_width = 128 self.preview_image_height = 64 self.preview_image_width_temp = 128 self.preview_image_height_temp = 64 self.output_image_width = 128 self.output_image_height = 64 self.output_image_width_temp = 128 self.output_image_height_temp = 64 self.bw_threshold = 127 self.bw_threshold_temp = 127 self.bw_invert = False self.bw_invert_temp = False self.dither_size = 0 self.dither_size_temp = 0 self.binarization_mode = 'threshold' self.binarization_mode_temp = 'threshold' self.binarization_equalizeHist = False self.binarization_equalizeHist_temp = False # init dll self.dithering = None self.error_diffusion = None self.load_dll() def start(self): if self.thread_run: return None self.thread_run = True self.thread.start() def stop(self): self.thread_run = False self.thread.join() def load_dll(self): dll_lib = CDLL("./image_processing/image_processing.dll") self.dithering = dll_lib.dithering self.error_diffusion = dll_lib.error_diffusion # set args type self.dithering.argtypes = [np.ctypeslib.ndpointer(c_uint8), c_int, c_int, c_int] self.dithering.restype = c_int self.error_diffusion.argtypes = [np.ctypeslib.ndpointer(c_uint8), c_int, c_int] self.error_diffusion.restype = c_int def set_threshold(self, value): if value != 0: self.bw_threshold_temp = value self.update_setting = True def set_dither_size(self, size): self.dither_size_temp = size self.update_setting = True def set_binarization_mode(self, mode): self.binarization_mode_temp = mode self.update_setting = True def set_invert(self, enable): if type(enable) == bool: self.bw_invert_temp = enable self.update_setting = True def set_equalizrHist(self, enable): if type(enable) == bool: self.binarization_equalizeHist_temp = enable self.update_setting = True def set_preview_size(self, width, height): self.preview_image_width_temp = width self.preview_image_height_temp = height self.update_setting = True def set_output_size(self, width, height): self.output_image_width_temp = width self.output_image_height_temp = height self.update_setting = True def update_parameters(self): if not self.update_setting: return None self.update_setting = False self.bw_threshold = self.bw_threshold_temp self.bw_invert = self.bw_invert_temp self.dither_size = self.dither_size_temp self.binarization_mode = self.binarization_mode_temp self.binarization_equalizeHist = self.binarization_equalizeHist_temp self.preview_image_width = self.preview_image_width_temp self.preview_image_height = self.preview_image_height_temp self.output_image_width = self.output_image_width_temp self.output_image_height = self.output_image_height_temp def input_image(self, image): self.input_queue.put(image, timeout=0.1) def output_clean(self): while self.output_queue.qsize() > 0: self.output_queue.get() def read_images(self): try: return self.output_queue.get(timeout=0.1) except: return None def install_complete_callback(self, callback): if callback != None: self.complete_callback = callback def remove_complete_callback(self): self.complete_callback = None def image_translate(self, image): # s1 = time.perf_counter() w = self.preview_image_width h = self.preview_image_height image_raw = cv.resize(image, (w, h)) image_gray = cv.cvtColor(image_raw, cv.COLOR_BGR2GRAY) if self.binarization_equalizeHist: image_gray = cv.equalizeHist(image_gray) image_out_gray_2x = cv.resize(image_gray, (2 * self.output_image_width, 2 * self.output_image_height)) image_out_gray_1x = cv.resize(image_gray, (self.output_image_width, self.output_image_height)) if self.binarization_mode == 'threshold': if not self.bw_invert: ret, image_bw = cv.threshold(image_gray, self.bw_threshold, 255, cv.THRESH_BINARY) ret, image_out_bw2x = cv.threshold(image_out_gray_2x, self.bw_threshold, 255, cv.THRESH_BINARY) ret, image_out_bw = cv.threshold(image_out_gray_1x, self.bw_threshold, 255, cv.THRESH_BINARY) else: ret, image_bw = cv.threshold(image_gray, self.bw_threshold, 255, cv.THRESH_BINARY_INV) ret, image_out_bw2x = cv.threshold(image_out_gray_2x, self.bw_threshold, 255, cv.THRESH_BINARY_INV) ret, image_out_bw = cv.threshold(image_out_gray_1x, self.bw_threshold, 255, cv.THRESH_BINARY_INV) elif self.binarization_mode == 'dithering': image_bw = image_gray.copy() self.dithering(image_bw, w, h, self.dither_size) image_out_bw2x = image_out_gray_2x self.dithering(image_out_bw2x, 2 * self.output_image_width, 2 * self.output_image_height, self.dither_size) image_out_bw = image_out_gray_1x self.dithering(image_out_bw, self.output_image_width, self.output_image_height, self.dither_size) elif self.binarization_mode == 'error_diff': image_bw = image_gray.copy() self.error_diffusion(image_bw, w, h) image_out_bw2x = image_out_gray_2x self.error_diffusion(image_out_bw2x, 2 * self.output_image_width, 2 * self.output_image_height) image_out_bw = image_out_gray_1x self.error_diffusion(image_out_bw, self.output_image_width, self.output_image_height) else: return None # s1 = time.perf_counter() image_out_bw_bytes = self.image_to_bw.convert(image_out_bw) # s2 = time.perf_counter() # dt = s2-s1 # print('dt: %.6f, fps: %.3f' % (dt, 1/dt)) self.output_images.raw = image_raw self.output_images.gray = image_gray self.output_images.bw = image_bw self.output_images.output_bw = image_out_bw self.output_images.output_bw2x = image_out_bw2x self.output_images.bytes = image_out_bw_bytes def output_images_to_queue(self): self.output_queue.put(self.output_images, timeout=0.1) def process_threading(self): while self.thread_run: try: image = self.input_queue.get(timeout=0.1) self.update_parameters() self.image_translate(image) self.output_images_to_queue() if self.complete_callback != None: self.complete_callback(self.output_queue) except: pass