def _handleException(self, e): u"""Реакция на исключение. Сбрасываем estimator в None (не пытаемся для простоты ничего реанимировать) устанавливаем информацию об ошибке в GUI""" self.estimator = None self.result_text.setText( "APPLICATION CRASHED" ) LOG.clear() LOG.write( "EXCEPTION OCCURED", str( e ) )
def _init_GUI( self ): u"""Создаем GUI, располагая все в вертикальный стек""" self.setWindowTitle("Sentimental Estimator") vbox = QtGui.QVBoxLayout() self.setLayout( vbox ) sentence_label = QtGui.QLabel( self ) sentence_label.setText( "Please, enter a sentence:" ) vbox.addWidget( sentence_label ) self.sentece_text = QtGui.QLineEdit( self ) vbox.addWidget( self.sentece_text ) process_button = QtGui.QPushButton( self ) process_button.setText( "PROCESS" ) process_button.clicked.connect(self._onProcess) vbox.addWidget( process_button ) result_label = QtGui.QLabel( self ) result_label.setText( "Result:" ) vbox.addWidget( result_label ) self.result_text = QtGui.QLineEdit( self ) vbox.addWidget( self.result_text ) log_label = QtGui.QLabel( self ) log_label.setText( "Log:" ) vbox.addWidget( log_label ) debug_log = GuiDebugHandler() vbox.addWidget( debug_log ) LOG.set_handler( debug_log ) LOG.set_enabled( True )
def _init_gui(self): self.setLayout(QtGui.QVBoxLayout()) image_label = QtGui.QLabel(self) image_label.setText("Please, enter image file path") self.layout().addWidget(image_label) image_path_layout = QtGui.QHBoxLayout() self.image_path_edit = QtGui.QLineEdit(self) process_button = QtGui.QPushButton(self) process_button.setText("Process") process_button.clicked.connect(self.on_process) image_path_layout.addWidget(self.image_path_edit) image_path_layout.addWidget(process_button) self.layout().addLayout(image_path_layout) self.preprocessImag = QtGui.QCheckBox(self) self.preprocessImag.setText( "Use image preprocessing (WARNING! Long operation!)") self.layout().addWidget(self.preprocessImag) tabs = QtGui.QTabWidget() self.original_image = ImageWidget(self) self.processed_image = ImageWidget(self) self.debug_log = GuiDebugHandler(self) tabs.addTab(self.original_image, "ORIGINAL") tabs.addTab(self.processed_image, "PROCESSED") tabs.addTab(self.debug_log, "LOG") LOG.set_handler(self.debug_log) LOG.set_enabled(True) self.layout().addWidget(tabs)
def write_debug_image_with_countours(image, message, countours): u"""Выводит в лог изображение с контурами""" if LOG.is_enabled(): if len(image.shape) == 2: image_copy = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR) else: image_copy = image.copy() cv2.drawContours(image_copy, countours, -1, (0, 255, 0), 3) LOG.write(message + " COUNTOURS(" + str(len(countours)) + ")", image_copy)
def _onProcess( self ): u"""Реакция на кнопку process. Запускаем estimator для введеного приложения""" if self.estimator == None: return LOG.clear() try: sentence = self.sentece_text.text() result = self.estimator.process_sentence( sentence ) self.result_text.setText( str( result ) ) except Exception as e: self._handleException( e )
def on_process(self): try: LOG.clear() image = cv2.imread(self.image_path_edit.text()) if image is None: raise Exception("Failed to open image \"" + self.image_path_edit.text() + "\"") self.original_image.set_image(image) processed_image = self.extractor.process_image( image, self.preprocessImag.isChecked()) self.processed_image.set_image(processed_image) except Exception as e: self._excpetion_message_box( "Failed to process image in case of exception", e)
def extract_rect(image, pts): u"""Извлекает прямоугольник pts из изображения image, применяя к нему преобразование исправления перспективы""" rect = order_points(pts) (tl, tr, br, bl) = rect maxWidth = max(int(np.linalg.norm(br - bl)), int(np.linalg.norm(tr - tl))) maxHeight = max(int(np.linalg.norm(br - tr)), int(np.linalg.norm(bl - tl))) dst = np.array([[0, 0], [maxWidth - 1, 0], [maxWidth - 1, maxHeight - 1], [0, maxHeight - 1]], dtype="float32") transform = cv2.getPerspectiveTransform(rect, dst) warped = cv2.warpPerspective(image, transform, (maxWidth, maxHeight)) LOG.write("[RECTANGLE EXTRACTOR] EXTRACTED", warped) return warped
def find_rects(image): u"""Ищем четырехугольники на сером изображении""" # Строим серое изображние gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) LOG.write("[RECTS FINDER] grayed", gray_image) # размытие улучшает поиск квадратов blured_img = cv2.GaussianBlur(gray_image, (5, 5), 0) LOG.write("[RECTS FINDER] blured", blured_img) # Бинаризация с поиском порога методом Оцу _, bin = cv2.threshold(blured_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) bin = cv2.dilate(bin, None) rects, supr_rects = find_suitable_rects(bin) write_debug_image_with_countours(bin, "[RECTS FINDER] OTSU", rects) if len(supr_rects) > 0: write_debug_image_with_countours(bin, "[RECTS FINDER] SUPRICIOUS OTSU", supr_rects) # Если на нашли на бинаризованном ОЦУ изображении прямоугольники, пробуем перебирать различные пороги # в ручную if len(rects) == 0: rects, sr = find_rects_enum_binarization(blured_img, 128) supr_rects.extend(sr) if len(rects) == 0: rects, sr = find_rects_enum_binarization(blured_img, 26) supr_rects.extend(sr) # Делать нечего. Прямоугольник - вся картинка if len(rects) == 0: if len(supr_rects) != 0: rects = supr_rects else: rects = [get_image_rect(image)] # Выводим найденные контуры write_debug_image_with_countours(image, "[RECTS FINDER] RESULT RECTS", rects) return rects
def __scores_by_dictionary(self, dict, words): u"""Вычисляет оценки предложения по словарю""" result = {"positive": 0, "negative": 0} if len(words) == 0: return result for w in words: positive_score = dict.positive_score(w) negative_score = dict.negative_score(w) result["positive"] = result["positive"] + positive_score result["negative"] = result["negative"] + negative_score LOG.write(w + " RESULT", "p: %d, n: %d" % (positive_score, negative_score)) result["positive"] = result["positive"] / len(words) result["negative"] = result["negative"] / len(words) return result
def split_sentece(sentece): u"""Разделяет предложение на слова, удаляет стоп-слова, знаки препинания и цифры""" clear_string_translation = str.maketrans( '', '', string.digits + R"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~""") clear_string = sentece.translate(clear_string_translation) LOG.write("CLEARED", clear_string) words = nltk.word_tokenize(clear_string) LOG.write("TOKENIZED", str(words)) words = normalize_words(words) LOG.write("NORMALIZED", str(words)) return [w for w in words if w not in stopwords.words('russian')]
def preprocess_image( image ): u"""Предобработка изображения""" result = image result = auto_contrast( result ) LOG.write( "[PREPROCESSOR] CONTRAST", result) result = sharpen( result ) LOG.write( "[PREPROCESSOR] SHARPEN", result ) result = cv2.fastNlMeansDenoisingColored( image, None, 10, 10, 7, 21 ) LOG.write( "[PREPROCESSOR] DENOISING", result ) return result
def process_sentence(self, sentence): u"""Обрабатываем предложение. Возвращает EstimatorResult""" LOG.write("START", sentence) words = mu.split_sentece(sentence) LOG.write("SPLITTED", str(words)) total_positive = 0 total_negative = 0 for dict in self.dictionaries: LOG.write("START DICTIONARY", dict["dict"].__class__.__name__) scores = self.__scores_by_dictionary(dict["dict"], words) total_positive = total_positive + dict["weight"] * scores[ "positive"] total_negative = total_negative + dict["weight"] * scores[ "negative"] LOG.write( "END DICTIONARY", "p: %f, n: %f" % (scores["positive"], scores["negative"])) LOG.write("TOTAL POSITIVE", str(total_positive)) LOG.write("TOTAL NEGATIVE", str(total_negative)) if total_negative == 0: if total_positive > 0: return EstimatorResult.positive else: return EstimatorResult.neutral else: ratio = total_positive / total_negative if ratio > self.neutral_treshold: return EstimatorResult.positive elif ratio < 1 / self.neutral_treshold: return EstimatorResult.negative else: return EstimatorResult.neutral