class MainView(QMainWindow): def __init__(self, title, parent=None): super(MainView, self).__init__(parent) self.setWindowTitle(title) self.vbox = QWidget(self) self.vlayout = QVBoxLayout(self.vbox) self.vlayout.setAlignment(Qt.AlignTop) # Create labeled combobox in vbox. self.labeled_combobox = ZLabeledComboBox(self.vbox, "LabledCombobox", orientation=Qt.Horizontal) self.vlayout.addWidget(self.labeled_combobox) #self.vbox.setLayout(self.vlayout) self.labeled_combobox.setGeometry(0, 0, 160, 60) self.labeled_combobox.add_activated_callback(self.combobox_activated) self.labeled_combobox.set_label("Months") items = ["January", "Februaty", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] self.labeled_combobox.add_items(items) self.setCentralWidget(self.vbox) self.show() def get_labeled_combobox(self): return self.labeled_combobox # comobobox activated callback. def combobox_activated(self, text): print("MainView.combobox_activated:{}".format(text))
class MainView(ZApplicationView): # Inner classes #-------------------------------------------- class SourceImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): self.load_opencv_image(filename) self.update() class DetectedImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): source_image = self.load_opencv_image(filename) self.gray_image = cv2.cvtColor(source_image, cv2.COLOR_RGB2GRAY) def detect(self, adaptive_method_id, threshold_type_id, block_size, threshold1, threshold2): MAX_PIXEL_VALUE = 255 C = 9.0 adapted_image = cv2.adaptiveThreshold(self.gray_image, MAX_PIXEL_VALUE, adaptive_method_id, threshold_type_id, block_size, C) detected_image = cv2.Canny(adapted_image, threshold1, threshold2) self.set_opencv_image(detected_image) self.update() #-------------------------------------------- # MainView Constructor def __init__(self, title, x, y, width, height): super(MainView, self).__init__(title, x, y, width, height) filename = "../images/SuperCar2.png" # 1 Create first imageview. self.source_image_view = self.SourceImageView(self) # 2 Create second imageview. self.detected_image_view = self.DetectedImageView(self) # 3 Load the file self.load_file(filename) # 4 Add imageviews to the main_layout which is a horizontal layouter. self.add(self.source_image_view) self.add(self.detected_image_view) self.detected_image_view.detect(self.adaptive_method_id, self.threshold_type_id, self.block_size, self.threshold1, self.threshold2) self.show() def add_control_pane(self, fixed_width=220): # Control pane widget self.block_size = 11 self.vpane = ZVerticalPane(self, fixed_width) self.adaptive_method_id = 0 self.threshold_type_id = 0 self.methods = { "ADAPTIVE_THRESH_MEAN_C": cv2.ADAPTIVE_THRESH_MEAN_C, "ADAPTIVE_THRESH_GAUSSIAN_C": cv2.ADAPTIVE_THRESH_GAUSSIAN_C } self.types = { "THRESH_BINARY": cv2.THRESH_BINARY, "THRESH_BINARY_INV": cv2.THRESH_BINARY_INV } self.adaptive_method = ZLabeledComboBox(self.vpane, "AdaptiveMethod") self.adaptive_method.add_items(list(self.methods.keys())) self.adaptive_method.add_activated_callback( self.adaptive_method_activated) self.threshold_type = ZLabeledComboBox(self.vpane, "ThresholdType") self.threshold_type.add_items(list(self.types.keys())) self.threshold_type.add_activated_callback( self.threshold_type_activated) self.block_size_slider = ZLabeledSlider(self.vpane, "BlockSize", take_odd=True, minimum=3, maximum=43, value=self.block_size, fixed_width=200) self.block_size_slider.add_value_changed_callback( self.block_size_changed) self.vpane.add(self.adaptive_method) self.vpane.add(self.threshold_type) self.vpane.add(self.block_size_slider) self.threshold1 = 50 self.threshold2 = 100 self.threshold1_slider = ZLabeledSlider(self.vpane, "Threshold1", take_odd=True, minimum=0, maximum=300, value=self.threshold1) self.threshold1_slider.add_value_changed_callback( self.slider1_value_changed) self.threshold2_slider = ZLabeledSlider(self.vpane, "Threshold2", take_odd=True, minimum=0, maximum=300, value=self.threshold2) self.threshold2_slider.add_value_changed_callback( self.slider2_value_changed) self.vpane.add(self.threshold1_slider) self.vpane.add(self.threshold2_slider) self.set_right_dock(self.vpane) def file_open(self): options = QFileDialog.Options() filename, _ = QFileDialog.getOpenFileName( self, "FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if filename: self.load_file(filename) def load_file(self, filename): self.source_image_view.load(filename) self.detected_image_view.load(filename) self.detected_image_view.detect(self.adaptive_method_id, self.threshold_type_id, self.block_size, self.threshold1, self.threshold2) self.set_filenamed_title(filename) def block_size_changed(self, value): self.block_size = int(value) if self.block_size % 2 == 0: # Block size should be odd. self.block_size = int((self.block_size * 2) / 2 + 1) #print("block_size_changed:{}".format(block_size)) self.detected_image_view.detect(self.adaptive_method_id, self.threshold_type_id, self.block_size, self.threshold1, self.threshold2) def adaptive_method_activated(self, text): self.adaptive_method_id = self.methods[text] #print("adaptive_method_activated:{}{}".format(text, self.adaptive_method_id)) self.detected_image_view.detect(self.adaptive_method_id, self.threshold_type_id, self.block_size, self.threshold1, self.threshold2) def threshold_type_activated(self, text): self.threshold_type_id = self.types[text] #print("threshold_type_activated:{}{}".format(text, self.threshold_type_id)) self.detected_image_view.detect(self.adaptive_method_id, self.threshold_type_id, self.block_size, self.threshold1, self.threshold2) def slider1_value_changed(self, value): self.threshold1 = int(value) #print("slider1_value_changed:{}".format(value)) self.detected_image_view.detect(self.adaptive_method_id, self.threshold_type_id, self.block_size, self.threshold1, self.threshold2) def slider2_value_changed(self, value): self.threshold2 = int(value) #print("slider2_value_changed:{}".format(value)) self.detected_image_view.detect(self.adaptive_method_id, self.threshold_type_id, self.block_size, self.threshold1, self.threshold2)
class MainView(ZApplicationView): # Inner classes #-------------------------------------------- class SourceImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): self.load_opencv_image(filename) self.update() class BinarizedImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): source_image = self.load_opencv_image(filename) image = cv2.GaussianBlur(source_image, (3,3), 0, 0, borderType = cv2.BORDER_DEFAULT ); self.gray_image = cv2.cvtColor(source_image, cv2.COLOR_RGB2GRAY) def binarize(self, adaptive_method_id, threshold_type_id, block_size): MAX_PIXEL_VALUE = 255 C = 9.0 binarizered_image = cv2.adaptiveThreshold(self.gray_image, MAX_PIXEL_VALUE, adaptive_method_id, threshold_type_id, block_size, C); self.set_opencv_image(binarizered_image) self.update() #-------------------------------------------- # MainView Constructor def __init__(self, title, x, y, width, height): super(MainView, self).__init__(title, x, y, width, height) filename = "images/flower.png" # 1 Create first imageview. self.source_image_view = self.SourceImageView(self) # 2 Create second imageview. self.binarized_image_view = self.BinarizedImageView(self) # 3 Load the file self.load_file(filename) # 4 Add two image views to a main_layout of this main view. self.add(self.source_image_view) self.add(self.binarized_image_view) self.show() def add_control_pane(self, fixed_width=220): # Control pane widget self.vpane = ZVerticalPane(self, fixed_width) self.block_size = 11 self.adaptive_method_id = 0; self.threshold_type_id = 0; self.methods = {"ADAPTIVE_THRESH_MEAN_C": cv2.ADAPTIVE_THRESH_MEAN_C, "ADAPTIVE_THRESH_GAUSSIAN_C": cv2.ADAPTIVE_THRESH_GAUSSIAN_C} self.types = {"THRESH_BINARY": cv2.THRESH_BINARY , "THRESH_BINARY_INV": cv2.THRESH_BINARY_INV } self.adaptive_method = ZLabeledComboBox(self.vpane, "AdaptiveMethod") self.adaptive_method.add_items(list(self.methods.keys() )) self.adaptive_method.add_activated_callback(self.adaptive_method_activated) self.threshold_type = ZLabeledComboBox(self.vpane, "ThresholdType") self.threshold_type.add_items(list(self.types.keys()) ) self.threshold_type.add_activated_callback(self.threshold_type_activated) self.labeled_slider = ZLabeledSlider(self.vpane, "BlockSize", take_odd =True, minimum=3, maximum=43, value=self.block_size, fixed_width=200) self.labeled_slider.add_value_changed_callback(self.slider_value_changed) self.vpane.add(self.adaptive_method) self.vpane.add(self.threshold_type) self.vpane.add(self.labeled_slider) self.set_right_dock(self.vpane) def file_open(self): options = QFileDialog.Options() filename, _ = QFileDialog.getOpenFileName(self,"FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if filename: self.load_file(filename) def load_file(self, filename): self.source_image_view.load(filename) self.binarized_image_view.load(filename) self.binarized_image_view.binarize(self.adaptive_method_id, self.threshold_type_id, self.block_size) self.set_filenamed_title(filename) def slider_value_changed(self, value): self.block_size = int(value) if self.block_size % 2 == 0: # Block size should be odd. self.block_size = int((self.block_size * 2)/2 + 1) #print("slider_value_changed:{}".format(block_size)) self.binarized_image_view.binarize(self.adaptive_method_id, self.threshold_type_id, self.block_size) def adaptive_method_activated(self, text): #print("adaptive_method_activated:{}".format(text)) self.adaptive_method_id = self.methods[text] self.binarized_image_view.binarize(self.adaptive_method_id, self.threshold_type_id, self.block_size) def threshold_type_activated(self, text): #print("threshold_type_activated:{}".format(text)) self.threshold_type_id = self.types[text] self.binarized_image_view.binarize(self.adaptive_method_id, self.threshold_type_id, self.block_size)
class MainView(ZApplicationView): # Inner classes #-------------------------------------------- class SourceImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): self.load_opencv_image(filename) self.update() class NonPhotorealisticView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): self.load_opencv_image(filename) self.update() def transform(self, renderer_type_id): print("transform {}".format(renderer_type_id)) try: src_image = self.get_opencv_image() self.transformed_image = None if src_image.any() != None: if renderer_type_id == MainView.EdgePreserveSmoothingByNormalizedConvolutionFilter: self.transformed_image = cv2.edgePreservingFilter( src_image, flags=1) if renderer_type_id == MainView.EdgePreserveSmoothingByRecursiveFilter: self.transformed_image = cv2.edgePreservingFilter( src_image, flags=2) if renderer_type_id == MainView.DetailEnhancement: self.transformed_image = cv2.detailEnhance(src_image) if renderer_type_id == MainView.MonochromePencilSketch: self.transformed_image, _ = cv2.pencilSketch( src_image, sigma_s=10, sigma_r=0.1, shade_factor=0.03) if renderer_type_id == MainView.ColorPencilSketch: _, self.transformed_image = cv2.pencilSketch( src_image, sigma_s=10, sigma_r=0.1, shade_factor=0.03) if renderer_type_id == MainView.Stylization: self.transformed_image = cv2.stylization(src_image) if self.transformed_image.all() != None: self.set_opencv_image(self.transformed_image) self.update() except: traceback.print_exc() #-------------------------------------------- # Class variables EdgePreserveSmoothingByNormalizedConvolutionFilter = 0 EdgePreserveSmoothingByRecursiveFilter = 1 DetailEnhancement = 2 MonochromePencilSketch = 3 ColorPencilSketch = 4 Stylization = 5 # MainView Constructor def __init__(self, title, x, y, width, height): super(MainView, self).__init__(title, x, y, width, height) self.filename = "../images/Figure.png" # 1 Create source imageview. self.source_image_view = self.SourceImageView(self) # 2 Create NonPhotorealisticView imageview. self.transformed_image_view = self.NonPhotorealisticView(self) # 3 Add two image views to a main_layout of this main view. self.add(self.source_image_view) self.add(self.transformed_image_view) # 4 Add a labeled combobox to top dock area self.add_renderer_combobox() # 5 Load the file self.load_file(self.filename) self.show() def add_renderer_combobox(self): self.renderer_id = MainView.EdgePreserveSmoothingByNormalizedConvolutionFilter self.renderer_combobox = ZLabeledComboBox(self, "RenderingType", Qt.Horizontal) self.renderers = { "EdgePreserve Smoothing By Normalized Convolution Filter": MainView.EdgePreserveSmoothingByNormalizedConvolutionFilter, "EdgePreserve Smoothing By Recursive Filter": MainView.EdgePreserveSmoothingByRecursiveFilter, "Detail Enhancement": MainView.DetailEnhancement, "Monochrome Pencil Sketch": MainView.MonochromePencilSketch, "Color Pencil Sketch": MainView.ColorPencilSketch, "Stylization": MainView.Stylization } self.renderer_combobox.add_items(self.renderers.keys()) self.renderer_combobox.add_activated_callback(self.renderer_activated) self.renderer_combobox.set_current_text(self.renderer_id) self.set_top_dock(self.renderer_combobox) # Show FileOpenDialog and select an image file. def file_open(self): options = QFileDialog.Options() filename, _ = QFileDialog.getOpenFileName( self, "FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if filename: self.load_file(filename) def load_file(self, filename): self.filename = filename self.source_image_view.load(filename) self.transformed_image_view.load(filename) self.transformed_image_view.transform(self.renderer_id) self.set_filenamed_title(filename) def renderer_activated(self, text): print("renderer_activated {} {}".format(text, self.renderer_id)) self.renderer_id = self.renderers[text] self.transformed_image_view.transform(self.renderer_id)
class MainView(ZApplicationView): FIRST = 0 SECOND = 1 THIRD = 2 DETECTOR_AKAZE = 0 DETECTOR_BRISK = 1 DETECTOR_ORB = 2 SOURCE_IMAGES = 2 # MainView Construsctor def __init__(self, title, x, y, width, height): super(MainView, self).__init__(title, x, y, width, height) self.filenames = ["../images/Tower1.png", "../images/Tower2.png", "../images/Blank.png"] self.grid = ZGridLayouter(self) self.image_views = [None, None, None] flags = cv2.IMREAD_COLOR # Create three imageviews. self.image_views[self.FIRST] = ZOpenCVImageView(self.grid, self.filenames[self.FIRST], flags) self.image_views[self.SECOND] = ZOpenCVImageView(self.grid, self.filenames[self.SECOND], flags) self.image_views[self.THIRD] = ZOpenCVImageView(self.grid, self.filenames[self.THIRD], flags) self.grid.add(self.image_views[self.FIRST], 0, 0) self.grid.add(self.image_views[self.SECOND], 0, 1) self.grid.add(self.image_views[self.THIRD], 1, 0, 1, 2) self.detector_id = self.DETECTOR_AKAZE self.detector= None self.show() # Redefined add_file_menu. def add_file_menu(self): # Typical file menu self.file_menu = QMenu('&File', self) self.file_menu.addAction('&New', self.file_new) self.file_menu.addAction('&Open First File', self.first_file_open) self.file_menu.addAction('&Open Second File', self.second_file_open) self.file_menu.addAction('&Save', self.file_save) self.file_menu.addAction('&Save As', self.file_save_as) self.file_menu.addAction('&Quit', self.file_quit) self.menuBar().addMenu(self.file_menu) # Add control pane to MainView def add_control_pane(self, fixed_width=200): # Control pane widget self.vpane = ZVerticalPane(self, fixed_width) # 1 Stitcher detector selection combobox self.detectors = {"AKAZEFeatureDetector" : self.DETECTOR_AKAZE, "BRISKFeatureDetector" : self.DETECTOR_BRISK, "ORBFeatureDetector" : self.DETECTOR_ORB} self.detector_id = self.DETECTOR_AKAZE self.detector_combobox = ZLabeledComboBox(self.vpane, "FeatureDetector") self.detector_combobox.add_activated_callback(self.detector_changed) self.detector_combobox.add_items(self.detectors.keys()) self.detector_combobox.set_current_text(self.detector_id) self.best_top = {"10" : 10, "20" : 20, "30" : 30, "40" : 40, "50" : 50, "60" : 60, "70" : 70, "80" : 80, "90" : 90, "100": 100} self.best_top_value = 10 self.best_top_combobox = ZLabeledComboBox(self.vpane, "BestTopNumber") self.best_top_combobox.add_activated_callback(self.best_top_changed) self.best_top_combobox.add_items(self.best_top.keys()) self.best_top_combobox.set_current_text(0) # Match pushbutton self.match_button = QPushButton("Match", self.vpane) self.match_button.clicked.connect(self.match_button_clicked) self.spacer = QLabel("", self.vpane) self.matched_number = QLabel("", self.vpane) self.vpane.add(self.detector_combobox) self.vpane.add(self.best_top_combobox) self.vpane.add(self.match_button) self.vpane.add(self.spacer) self.vpane.add(self.matched_number) self.set_right_dock(self.vpane) def first_file_open(self): options = QFileDialog.Options() self.filenames[self.FIRST], _ = QFileDialog.getOpenFileName(self,"FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if self.filenames[self.FIRST]: self.image_views[self.FIRST].load_opencv_image(self.filenames[self.FIRST], cv2.IMREAD_COLOR) filename = self.filenames[self.FIRST] + " " + self.filenames[self.SECOND] self.set_filenamed_title(filename) def second_file_open(self): options = QFileDialog.Options() self.filenames[self.SECOND], _ = QFileDialog.getOpenFileName(self,"FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if self.filenames[self.SECOND]: self.image_views[self.SECOND].load_opencv_image(self.filenames[self.SECOND], cv2.IMREAD_COLOR) filename = self.filenames[self.FIRST] + " " + self.filenames[self.SECOND] self.set_filenamed_title(filename) # Detector Combobox changed callback. def detector_changed(self, text): self.detector_id = self.detectors[text] self.feature_matching() # Best_top Combobox changed callback. def best_top_changed(self, text): self.best_top_value = int(text) print("Best top value {}".format(self.best_top_value)) self.matched_number self.feature_matching() # Match button clicked callback def match_button_clicked(self): self.feature_matching() # Feature matching operation. def feature_matching(self): try: self.detector = None # 1 Create a feature detector by self.detector_id. if self.detector_id == self.DETECTOR_AKAZE: self.detector = cv2.AKAZE_create() if self.detector_id == self. DETECTOR_BRISK: self.detector = cv2.BRISK_create() if self.detector_id == self.DETECTOR_ORB: self.detector = cv2.ORB_create() self.keypoints = [None, None] self.descriptors = [None, None] self.images = [None, None] # 2 Call dector.detectAndCompute for i in range(self.SOURCE_IMAGES): self.images[i] = self.image_views[i ].get_opencv_image() self.keypoints[i], self.descriptors[i] = self.detector.detectAndCompute(self.images[i], None) # 3 Create Brute-Force Matcher object. bf_matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) # 4 Match two descriptors by using bf_matcher. matches = bf_matcher.match(self.descriptors[self.FIRST], self.descriptors[self.SECOND]) # 5 Update matche_number label. self.total_matched_number = len(matches) label = "Matched Number:" + str(self.best_top_value) + "/" + str(self.total_matched_number) self.matched_number.setText(label) print("matched number {}".format(len(matches))) # 6 Sort matches by distance. matches = sorted(matches, key=lambda x:x.distance) # 7 Call cv2.drawMatches. out_image = self.images[self.FIRST] matched_image = cv2.drawMatches(self.images[self.FIRST], self.keypoints[self.FIRST], self.images[self.SECOND], self.keypoints[self.SECOND], matches[:self.best_top_value], out_image, flags=2) # 8 Set matched_image to the THIRD image_view self.image_views[self.THIRD].set_opencv_image(matched_image); self.image_views[self.THIRD].update() except: traceback.print_exc()
class MainView(ZApplicationView): # Inner classes #-------------------------------------------- class SourceImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): self.load_opencv_image(filename) self.update() class TransformedImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): self.load_opencv_image(filename) def transform(self, shape_id, ksize): src_image = self.get_opencv_image() element = cv2.getStructuringElement(shape_id, (ksize, ksize), (-1, -1)) transformed_image = cv2.dilate(src_image, element) if transformed_image.all() != None: self.set_opencv_image(transformed_image) self.update() #-------------------------------------------- # MainView Constructor def __init__(self, title, x, y, width, height): super(MainView, self).__init__(title, x, y, width, height) filename = "../images/HelloWorld.png" # 1 Create first imageview. self.source_image_view = self.SourceImageView(self) # 2 Create second imageview. self.transformed_image_view = self.TransformedImageView(self) # 3 Load the file self.load_file(filename) # 4 Add two image views to a main_layout of this main view. self.add(self.source_image_view) self.add(self.transformed_image_view) self.show() def add_control_pane(self, fixed_width=220): # Control pane widget self.vpane = ZVerticalPane(self, fixed_width) self.ksize = 3 self.shape_id = 2 self.shapes = {"MORPH_RECT": 0, "MORPH_CROSS": 1, "MORPH_ELLIPSE": 2} self.shape = ZLabeledComboBox(self.vpane, "AdaptiveMethod") self.shape.add_items(list(self.shapes.keys())) self.shape.add_activated_callback(self.shape_activated) self.ksize_slider = ZLabeledSlider(self.vpane, "KernelSize", take_odd=True, minimum=1, maximum=33, value=self.ksize, fixed_width=200) self.ksize_slider.add_value_changed_callback(self.ksize_value_changed) self.vpane.add(self.shape) self.vpane.add(self.ksize_slider) self.set_right_dock(self.vpane) def file_open(self): options = QFileDialog.Options() filename, _ = QFileDialog.getOpenFileName( self, "FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if filename: self.load_file(filename) def load_file(self, filename): self.source_image_view.load(filename) self.transformed_image_view.load(filename) self.transformed_image_view.transform(self.shape_id, self.ksize) self.set_filenamed_title(filename) def ksize_value_changed(self, value): self.ksize = int(value) if self.ksize % 2 == 0: self.ksize = int((self.ksize * 2) / 2 + 1) # Block size should be odd. #print("ksize_value_changed:{}".format(ksize)) self.transformed_image_view.transform(self.shape_id, self.ksize) def shape_activated(self, text): self.shape_id = self.shapes[text] print("shape_activated:{} {}".format(text, self.shape_id)) self.transformed_image_view.transform(self.shape_id, self.ksize)
class MainView(ZApplicationView): FIRST = 0 SECOND = 1 THIRD = 2 # MainView Constructor def __init__(self, title, x, y, width, height): super(MainView, self).__init__(title, x, y, width, height) self.filenames = [ "../images/Lake2.png", "../images/Lake1.png", "../images/Blank.png" ] self.grid = ZGridLayouter(self) self.image_views = [None, None, None] flags = cv2.IMREAD_COLOR # 1 Create first imageview. self.image_views[self.FIRST] = ZOpenCVImageView( self.grid, self.filenames[self.FIRST], flags) self.image_views[self.SECOND] = ZOpenCVImageView( self.grid, self.filenames[self.SECOND], flags) self.image_views[self.THIRD] = ZOpenCVImageView( self.grid, self.filenames[self.THIRD], flags) self.grid.add(self.image_views[self.FIRST], 0, 0) self.grid.add(self.image_views[self.SECOND], 0, 1) self.grid.add(self.image_views[self.THIRD], 1, 0, 1, 2) self.mode = False #cv2.cv.PANORAMA #self.stitcher = cv2.createStitcher(self.mode) self.stitcher = cv2.Stitcher_create(self.mode) self.stitch() self.show() # Redefined add_file_menu. def add_file_menu(self): # Typical file menu self.file_menu = QMenu('&File', self) self.file_menu.addAction('&New', self.file_new) self.file_menu.addAction('&Open First File', self.first_file_open) self.file_menu.addAction('&Open Second File', self.second_file_open) self.file_menu.addAction('&Save', self.file_save) self.file_menu.addAction('&Save As', self.file_save_as) self.file_menu.addAction('&Quit', self.file_quit) self.menuBar().addMenu(self.file_menu) # Add control pane to MainView def add_control_pane(self, fixed_width=130): # Control pane widget self.ksize = 11 self.vpane = ZVerticalPane(self, fixed_width) # 1 Stitcher mode selection combobox self.modes = {"PANORAM": 0, "SCANS": 1} self.labeled_combobox = ZLabeledComboBox(self.vpane, "Sticher Mode") self.labeled_combobox.add_activated_callback(self.mode_changed) self.labeled_combobox.add_items(self.modes.keys()) # Stitch pushbutton self.stitch_button = QPushButton("Stitch", self.vpane) self.stitch_button.clicked.connect(self.stitch) self.vpane.add(self.labeled_combobox) self.vpane.add(self.stitch_button) self.set_right_dock(self.vpane) def first_file_open(self): options = QFileDialog.Options() self.filenames[self.FIRST], _ = QFileDialog.getOpenFileName( self, "FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if self.filenames[self.FIRST]: self.image_views[self.FIRST].load_opencv_image( self.filenames[self.FIRST], cv2.IMREAD_COLOR) filename = self.filenames[self.FIRST] + " " + self.filenames[ self.SECOND] #self.stitch() self.set_filenamed_title(filename) def second_file_open(self): options = QFileDialog.Options() self.filenames[self.SECOND], _ = QFileDialog.getOpenFileName( self, "FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if self.filenames[self.SECOND]: self.image_views[self.SECOND].load_opencv_image( self.filenames[self.SECOND], cv2.IMREAD_COLOR) filename = self.filenames[self.FIRST] + " " + self.filenames[ self.SECOND] #self.stitch() self.set_filenamed_title(filename) # combobox changed callback. def mode_changed(self, text): new_mode = self.modes[text] print("prev mode {}".format(self.mode)) if new_mode != self.mode: # Need to recreate stitcher object. self.mode = new_mode print("Recreated new stitcher {}".format(self.mode)) self.stitcher = cv2.createStitcher(self.mode) # self.stitch() def stitch(self): image1 = self.image_views[self.FIRST].get_opencv_image() image2 = self.image_views[self.SECOND].get_opencv_image() if image1.all() == None or image2.all() == None: QMessageBox.critical(self, "Stitcher ", "First and/or second image is empty!") return images = (image1, image2) status, stitched_image = self.stitcher.stitch(images, self.mode) if status == 0: print("Stitched two images") self.image_views[self.THIRD].set_opencv_image(stitched_image) self.image_views[self.THIRD].update() else: error = self.get_error_message(status) QMessageBox.critical(self, "Stitcher Failed", error) def get_error_message(self, key): key = str(key) status = { #"0": "OK", "1": "Err_Need_More_Image", "2": "Err_Homography_Est_Fail", "3": "Err_Camera_Params_Adjust_Fail" } return status[key]
class MainView(ZApplicationView): # Inner classes #-------------------------------------------- class SourceImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): self.load_opencv_image(filename) self.update() class DetectedImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): self.load_opencv_image(filename) def detect(self, hog_descriptor_id, stride): detected_image = self.get_opencv_image().copy() self.hog = None if hog_descriptor_id == MainView.DEFAULT: winSize = (64, 128) blockSize = (16, 16) blockStride = (8, 8) cellSize = (8, 8) nbins = 9 self.hog = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins) self.hog.setSVMDetector( cv2.HOGDescriptor_getDefaultPeopleDetector()) if hog_descriptor_id == MainView.DAIMLER: winSize = (48, 96) blockSize = (16, 16) blockStride = (8, 8) cellSize = (8, 8) nbins = 9 self.hog = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins) self.hog.setSVMDetector( cv2.HOGDescriptor_getDaimlerPeopleDetector()) if hog_descriptor_id == MainView.USER_DEFINED: winSize = (32, 64) blockSize = (8, 8) blockStride = (4, 4) cellSize = (4, 4) nbins = 9 self.hog = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins) self.hog.setSVMDetector( cv2.HOGDescriptor_getDefaultPeopleDetector()) (rectangles, weights) = self.hog.detectMultiScale(detected_image, hitThreshold=0, winStride=(stride, stride), padding=(0, 0), scale=1.05, finalThreshold=2) for (x, y, w, h) in rectangles: cv2.rectangle(detected_image, (x, y), (x + w, y + h), (0, 0, 255), 2) self.set_opencv_image(detected_image) self.update() #-------------------------------------------- DEFAULT = 0 DAIMLER = 1 USER_DEFINED = 2 # MainView Constructor def __init__(self, title, x, y, width, height): super(MainView, self).__init__(title, x, y, width, height) filename = "../images/Pedestrian.png" # 1 Create first imageview. self.source_image_view = self.SourceImageView(self) # 2 Create second imageview. self.detected_image_view = self.DetectedImageView(self) # 3 Load the file self.load_file(filename) # 4 Add two image views to a main_layout of this main view. self.add(self.source_image_view) self.add(self.detected_image_view) self.show() def add_control_pane(self, fixed_width=220): # Control pane widget self.vpane = ZVerticalPane(self, fixed_width) self.stride = 6 self.hog_descriptor_id = self.DEFAULT self.hog_descriptors = { "Default": self.DEFAULT, "Daimler": self.DAIMLER, "UserDefined": self.USER_DEFINED } self.hog_descriptor = ZLabeledComboBox(self.vpane, "HOG Descriptor") self.hog_descriptor.add_items(list(self.hog_descriptors.keys())) self.hog_descriptor.add_activated_callback( self.hog_descriptor_activated) self.hog_descriptor.set_current_text(self.hog_descriptor_id) self.stride_slider = ZLabeledSlider(self.vpane, "WinStride", take_odd=False, minimum=1, maximum=16, value=self.stride, fixed_width=180) self.stride_slider.add_value_changed_callback( self.stride_value_changed) self.vpane.add(self.hog_descriptor) self.vpane.add(self.stride_slider) self.set_right_dock(self.vpane) def file_open(self): options = QFileDialog.Options() filename, _ = QFileDialog.getOpenFileName( self, "FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if filename: self.load_file(filename) def load_file(self, filename): self.source_image_view.load(filename) self.detected_image_view.load(filename) self.detected_image_view.detect(self.hog_descriptor_id, self.stride) self.set_filenamed_title(filename) def stride_value_changed(self, value): self.stride = int(value) self.detected_image_view.detect(self.hog_descriptor_id, self.stride) def hog_descriptor_activated(self, text): self.hog_descriptor_id = self.hog_descriptors[text] print("hog_descriptor_activated:{} {}".format(text, self.hog_descriptor_id)) self.detected_image_view.detect(self.hog_descriptor_id, self.stride)
class MainView(ZApplicationView): # Inner classes #--------------------------------------------------------- class BinarizedImageView(ZOpenCVImageView): def __init__(self, parent, filename=None, flags=cv2.IMREAD_COLOR): ZOpenCVImageView.__init__(self, parent, filename, flags) src_mage = self.get_opencv_image() self.gray_image = cv2.cvtColor(src_mage, cv2.COLOR_BGR2GRAY) print("BinarizedImage") self.binarized_image = None def get_binarized_image(self): return self.binarized_image def binarize(self, threshold_type, threshold_value): try: THRESHOLD_VALUE_MAX = 255 _, self.binarized_image = cv2.threshold( self.gray_image, threshold_value, THRESHOLD_VALUE_MAX, threshold_type) #self.update() #print("bin {}".format(self.binarized_image.shape)) return self.binarized_image except: traceback.print_exc() class MatchedImageView(ZOpenCVImageView): def __init__(self, parent, filename=None, flags=cv2.IMREAD_COLOR): ZOpenCVImageView.__init__(self, parent, filename, flags) def set_matched_image(self, image): self.set_opencv_image(image) self.update() def set_image(self, image): self.set_opencv_image(image) self.update() #--------------------------------------------------------- FIRST = 0 SECOND = 1 THIRD = 2 # MainView Constructor def __init__(self, title, x, y, width, height): super(MainView, self).__init__(title, x, y, width, height) self.filenames = [ "../images/CatImage.png", "../images/CatFace.png", "../images/Blank.png" ] self.image_views = [None, None, None] self.grid = ZGridLayouter(self) flags = cv2.IMREAD_COLOR # 1 Create three image views. self.image_views[self.FIRST] = self.BinarizedImageView( self, self.filenames[self.FIRST], flags) self.image_views[self.SECOND] = self.BinarizedImageView( self, self.filenames[self.SECOND], flags) self.image_views[self.THIRD] = self.MatchedImageView( self, self.filenames[self.THIRD], flags) # 2 Add the image views to the grid layouter. self.grid.add(self.image_views[self.FIRST], 0, 0) self.grid.add(self.image_views[self.SECOND], 0, 1) self.grid.add(self.image_views[self.THIRD], 1, 0, 1, 2) filename = self.filenames[self.FIRST] + " " + self.filenames[ self.SECOND] self.set_filenamed_title(filename) self.show() # Redefined add_file_menu. def add_file_menu(self): # Typical file menu self.file_menu = QMenu('&File', self) self.file_menu.addAction('&New', self.file_new) self.file_menu.addAction('&Open First File', self.first_file_open) self.file_menu.addAction('&Open Second File', self.second_file_open) self.file_menu.addAction('&Save', self.file_save) self.file_menu.addAction('&Save As', self.file_save_as) self.file_menu.addAction('&Quit', self.file_quit) self.menuBar().addMenu(self.file_menu) def add_control_pane(self, fixed_width=200): # Control pane widget self.threshold_value = 11 self.vpane = ZVerticalPane(self, fixed_width) self.threshold_type_id = 0 self.types = { "THRESH_BINARY": cv2.THRESH_BINARY, "THRESH_BINARY_INV": cv2.THRESH_BINARY_INV, "THRESH_TRUNC": cv2.THRESH_TRUNC, "THRESH_TOZERO": cv2.THRESH_TOZERO, "THRESH_TOZERO_INV": cv2.THRESH_TOZERO_INV, "THRESH_OTSU": cv2.THRESH_OTSU, "THRESH_TRIANGLE": cv2.THRESH_TRIANGLE } self.threshold_type = ZLabeledComboBox(self.vpane, "ThresholdType") self.threshold_type.add_items(list(self.types.keys())) self.threshold_type.add_activated_callback( self.threshold_type_activated) self.threshold_type.set_current_text(self.threshold_type_id) self.threshold_value = 60 self.threshold_value_slider = ZLabeledSlider( self.vpane, "ThresholdValue", take_odd=True, minimum=0, maximum=255, value=self.threshold_value, fixed_width=200) self.threshold_value_slider.add_value_changed_callback( self.threshold_value_changed) self.vpane.add(self.threshold_type) self.vpane.add(self.threshold_value_slider) self.match_min_size = 60 self.match_max_size = 240 self.match_min_size_slider = ZLabeledSlider(self.vpane, "MatchMinSize", take_odd=True, minimum=10, maximum=100, value=self.match_min_size) self.match_min_size_slider.add_value_changed_callback( self.match_min_size_value_changed) self.match_max_size_slider = ZLabeledSlider(self.vpane, "MatchMaxSize", take_odd=True, minimum=100, maximum=400, value=self.match_max_size) self.match_max_size_slider.add_value_changed_callback( self.match_max_size_value_changed) self.vpane.add(self.match_min_size_slider) self.vpane.add(self.match_max_size_slider) self.clear_button = QPushButton("Clear", self.vpane) self.clear_button.clicked.connect(self.clear_button_clicked) self.match_button = QPushButton("Match", self.vpane) self.match_button.clicked.connect(self.match_button_clicked) self.vpane.add(self.clear_button) self.vpane.add(self.match_button) self.set_right_dock(self.vpane) def first_file_open(self): options = QFileDialog.Options() filename, _ = QFileDialog.getOpenFileName( self, "FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if filename: self.filenames[self.FIRST] = filename self.image_views[self.FIRST].load_opencv_image(filename) self.image_views[self.THIRD].load_opencv_image( self.filenames[self.THIRD]) filename = self.filenames[self.FIRST] + " " + self.filenames[ self.SECOND] self.set_filenamed_title(filename) def second_file_open(self): options = QFileDialog.Options() filename, _ = QFileDialog.getOpenFileName( self, "FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if filename: self.filenames[self.SECOND] = filename self.image_views[self.SECOND].load_opencv_image(filename) self.image_views[self.THIRD].load_opencv_image( self.filenames[self.THIRD]) filename = self.filenames[self.FIRST] + " " + self.filenames[ self.SECOND] self.set_filenamed_title(filename) def threshold_type_activated(self, text): self.threshold_type_id = self.types[text] self.shapeMatching() def threshold_value_changed(self, value): self.threshold_value = int(value) if self.threshold_value % 2 == 0: # Block size should be odd. self.threshold_value = int((self.threshold_value * 2) / 2 + 1) self.shapeMatching() def match_min_size_value_changed(self, value): self.match_min_size = int(value) self.shapeMatching() def match_max_size_value_changed(self, value): self.match_max_size = int(value) self.shapeMatching() def clear_button_clicked(self): src_image = self.image_views[self.FIRST].get_opencv_image().copy() self.image_views[self.THIRD].set_image(src_image) def match_button_clicked(self): self.shapeMatching() # Shape matching operation to two images in image_views[self.FIRST] and image_views[self.SECOND]. # A matched rectangle will be draw on image_views[self.THIRD]. def shapeMatching(self): src_image = self.image_views[self.FIRST].get_opencv_image().copy() self.image_views[self.THIRD].set_image(src_image) src_bin = self.image_views[self.FIRST].binarize( self.threshold_type_id, self.threshold_value) tmp_bin = self.image_views[self.SECOND].binarize( self.threshold_type_id, self.threshold_value) nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats( src_bin) print("labels:{}".format(nlabels)) dest_image = src_image.copy() MATCHING_THRESHOLD = 0.005 minimum = [0, 0, 0, 0] #cv2.Rect(0, 0, 0, 0) MIN_SIMILARITY = 1.0 found = False CV_CONTOURS_MATCH_I1 = 1 for i in range(nlabels): x, y, w, h, a = stats[i] rect = [x, y, w, h] # Region of interest roi = src_bin[y:(y + h), x:(x + w)] similarity = cv2.matchShapes( tmp_bin, roi, CV_CONTOURS_MATCH_I1, 0) #method=CV_CONTOURS_MATCH_I1, parameter=0); if ((w >= self.match_min_size or h >= self.match_min_size) and (w <= self.match_max_size or h <= self.match_max_size)): if (similarity <= MIN_SIMILARITY): MIN_SIMILARITY = similarity minimum = rect print("matching similarity={} x={} y={} w={} h={}".format( similarity, x, y, w, h)) found = True if found: x, y, w, h = minimum cv2.rectangle(dest_image, (x, y), (x + w, y + h), (0, 0, 255), 3) self.image_views[self.THIRD].set_matched_image(dest_image)
class MainView(ZApplicationView): # Inner classes #-------------------------------------------- class SourceImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): self.load_opencv_image(filename) self.update() class BinarizedImageView(ZOpenCVImageView): def __init__(self, parent): ZOpenCVImageView.__init__(self, parent) def load(self, filename): image = self.load_opencv_image(filename) self.source_image = image.copy() #self.gray_image = cv2.cvtColor(self.source_image, cv2.COLOR_RGB2GRAY) self.gray_image = cv2.cvtColor(self.source_image, cv2.COLOR_BGR2GRAY) def binarize(self, adaptive_method_id, threshold_type_id, block_size): MAX_PIXEL_VALUE = 255 C = 9.0 self.binarizered_image = cv2.adaptiveThreshold( self.gray_image, MAX_PIXEL_VALUE, adaptive_method_id, threshold_type_id, block_size, C) #self.set_opencv_image(binarizered_image) self.update() def detect_connected_components(self): target = self.source_image.copy() nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats( self.binarizered_image, 4) #stats = cv2.connectedComponentsWithStats(self.gray_image) print("labels:{}".format(nlabels)) ih, iw, c = target.shape print("target:width={} height={} channels={}".format(iw, ih, c)) for i in range(nlabels): x, y, w, h, a = stats[i] print("x,y,w,h, a={},{},{},{}, {}".format(x, y, w, h, a)) cv2.rectangle(target, (x, y), (x + w, y + h), (0, 0, 255), 3) self.set_opencv_image(target) self.update() #-------------------------------------------- # MainView Constructor def __init__(self, title, x, y, width, height): super(MainView, self).__init__(title, x, y, width, height) filename = "../images/Shapes.png" # 1 Create first imageview. self.source_image_view = self.SourceImageView(self) # 2 Create second imageview. self.binarized_image_view = self.BinarizedImageView(self) # 3 Load the file self.load_file(filename) # 4 Add two image views to a main_layout of this main view. self.add(self.source_image_view) self.add(self.binarized_image_view) self.show() def add_control_pane(self, fixed_width=220): # Control pane widget self.block_size = 11 self.vpane = ZVerticalPane(self, fixed_width) self.adaptive_method_id = 0 self.threshold_type_id = 0 self.methods = { "ADAPTIVE_THRESH_MEAN_C": cv2.ADAPTIVE_THRESH_MEAN_C, "ADAPTIVE_THRESH_GAUSSIAN_C": cv2.ADAPTIVE_THRESH_GAUSSIAN_C } self.types = { "THRESH_BINARY": cv2.THRESH_BINARY, "THRESH_BINARY_INV": cv2.THRESH_BINARY_INV } self.adaptive_method = ZLabeledComboBox(self.vpane, "AdaptiveMethod") self.adaptive_method.add_items(list(self.methods.keys())) self.adaptive_method.add_activated_callback( self.adaptive_method_activated) self.threshold_type = ZLabeledComboBox(self.vpane, "ThresholdType") self.threshold_type.add_items(list(self.types.keys())) self.threshold_type.add_activated_callback( self.threshold_type_activated) self.labeled_slider = ZLabeledSlider(self.vpane, "BlockSize", take_odd=True, minimum=3, maximum=43, value=self.block_size, fixed_width=200) self.labeled_slider.add_value_changed_callback( self.slider_value_changed) self.vpane.add(self.adaptive_method) self.vpane.add(self.threshold_type) self.vpane.add(self.labeled_slider) self.set_right_dock(self.vpane) def file_open(self): options = QFileDialog.Options() filename, _ = QFileDialog.getOpenFileName( self, "FileOpenDialog", "", "All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options) if filename: self.load_file(filename) def load_file(self, filename): self.source_image_view.load(filename) self.binarized_image_view.load(filename) self.binarized_image_view.binarize(self.adaptive_method_id, self.threshold_type_id, self.block_size) self.binarized_image_view.detect_connected_components() self.set_filenamed_title(filename) def slider_value_changed(self, value): self.block_size = int(value) if self.block_size % 2 == 0: self.block_size = int((self.block_size * 2) / 2 + 1) # Block size should be odd. print("slider_value_changed:{}".format(self.block_size)) self.binarized_image_view.binarize(self.adaptive_method_id, self.threshold_type_id, self.block_size) self.binarized_image_view.detect_connected_components() def adaptive_method_activated(self, text): print("adaptive_method_activated:{}".format(text)) self.adaptive_method_id = self.methods[text] self.binarized_image_view.binarize(self.adaptive_method_id, self.threshold_type_id, self.block_size) self.binarized_image_view.detect_connected_components() def threshold_type_activated(self, text): print("threshold_type_activated:{}".format(text)) self.threshold_type_id = self.types[text] self.binarized_image_view.binarize(self.adaptive_method_id, self.threshold_type_id, self.block_size) self.binarized_image_view.detect_connected_components()