如何将第一个处理图像(例如 Canny 过滤器)的输出作为另一个处理过滤器的输入?

Posted

技术标签:

【中文标题】如何将第一个处理图像(例如 Canny 过滤器)的输出作为另一个处理过滤器的输入?【英文标题】:How do I take the output of the first processed image(e.g., Canny Filter) as input to another process filter? 【发布时间】:2020-12-15 23:31:52 【问题描述】:

如何将第一个处理后的图像(例如 Canny 过滤器)的输出作为另一个处理/过滤器(例如 Sobel 过滤器)的输入,而不是对原始图像应用任何过滤器?

在应用任何过滤器之前

应用过滤器后

每当我应用另一个进程时,它都会在原始图像上再次完成(不是第一个进程/过滤器的输出)。

代码:-

import sys
import numpy as np
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import cv2

class Ui_MainWindow(QMainWindow):
    global img

    def __init__(self):
        super().__init__()

        self.init_Main_Ui()
        self.init_Menu_Ui()

    def init_Main_Ui(self):
        self.setObjectName("test")
        self.setEnabled(True)
        self.resize(1200, 700)
        self.setMinimumSize(QtCore.QSize(500, 300))
        self.setMaximumSize(QtCore.QSize(500, 300))

        self.image_label = QLabel(self)

        self.setCentralWidget(self.image_label)

        self.show()

    def init_Menu_Ui(self):
        global img
        menu_bar = self.menuBar()
        menu_bar.setNativeMenuBar(False)

        file_menu = menu_bar.addMenu('&File')  # &가 alt+F 메뉴 단축키 지정

        Exit_action = QAction('Exit', self)
        Exit_action.setShortcut('Ctrl+Q')
        Exit_action.triggered.connect(qApp.quit)

        Open_action = QAction('open', self)
        Open_action.setShortcut('Ctrl+O')
        Open_action.triggered.connect(self.read_file)

        file_menu.addAction(Open_action)
        file_menu.addAction(Exit_action)

        self.filter_menu = menu_bar.addMenu("&Filter")
        self.filter_menu.setEnabled(False)

        Sobel_action = QAction('Sobel filter', self)
        Sobel_action.setShortcut('Alt+1')
        Sobel_action.triggered.connect(
            lambda: self.Sobel_filter(img)
        )

        Prewitt_action = QAction('Prewitt filter', self)
        Prewitt_action.setShortcut('Alt+2')
        Prewitt_action.triggered.connect(
            lambda : self.Prewitt_filter(img)
        )

        Gaussian_action = QAction('Gaussian filter', self)
        Gaussian_action.setShortcut('Alt+3')
        Gaussian_action.triggered.connect(
            lambda : self.Gaussian_filter(img)
        )


        Canny_action = QAction('Canny filter', self)
        Canny_action.setShortcut('Alt+4')
        Canny_action.triggered.connect(
            lambda : self.Canny_filter(img)
        )

        LoG_action = QAction('LoG filter', self)
        LoG_action.setShortcut('Alt+5')
        LoG_action.triggered.connect(
            lambda : self.LoG_filter(img)
        )
        
        self.setWindowTitle('Image Processing')
        self.filter_menu.addAction(Sobel_action)
        self.filter_menu.addAction(Prewitt_action)
        self.filter_menu.addAction(Gaussian_action)

    def read_file(self):
        global img
        file_name = QFileDialog.getOpenFileName(self)

        if file_name[0] is not '':
            img0 = cv2.imread(file_name[0])

            img = cv2.cvtColor(img0, cv2.COLOR_BGR2RGB)

            self.reshow_image(img)
            print('aa')
            self.filter_menu.setEnabled(True)
        else:
            print('please put img')

    def save_image(self):
        print("save")

    def Sobel_filter(self, img):
        img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

        sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
        sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)

        sobel = img.copy()
        height = np.size(img, 0)
        width = np.size(img, 1)

        for i in range(width):
            for j in range(height):
                sobel[j, i] = np.minimum(255, np.round(np.sqrt(sobelx[j, i] * sobelx[j, i] + sobely[j, i] * sobely[j, i])))

        sobel = cv2.cvtColor(sobel, cv2.COLOR_GRAY2RGB)
        cv2.imwrite("Sobel Filtered Image.png", sobel)
        self.reshow_image(sobel)


    def Prewitt_filter(self, img):
        img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

        kernelx = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]])
        kernely = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])

        img_prewittx = cv2.filter2D(img, -1, kernelx)
        img_prewitty = cv2.filter2D(img, -1, kernely)

        Prewitt = cv2.cvtColor(img_prewittx + img_prewitty, cv2.COLOR_GRAY2RGB)
        self.reshow_image(Prewitt)


    def Gaussian_filter(self, img):
        img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        img_smooth = cv2.GaussianBlur(img, (3, 3), 0)
        img_smooth = cv2.cvtColor(img_smooth, cv2.COLOR_GRAY2RGB)
        self.reshow_image(img_smooth)

    def reshow_image(self, cv_img):
        if cv_img is not None:
            self.image_label.resize(cv_img.shape[1], cv_img.shape[0])
            Q_img = QImage(cv_img.data, cv_img.shape[1], cv_img.shape[0], cv_img.shape[1] * 3, QImage.Format_RGB888)
            self.image_label.setPixmap(QPixmap.fromImage(Q_img))
        else:
            print("Image load failed")


    def exit(self):
        cv2.waitKey(0)
        cv2.destroyAllWindows()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    ui = Ui_MainWindow()
    sys.exit(app.exec_())

【问题讨论】:

我不明白问题出在哪里。也许每个过滤器都应该将结果分配给变量 - 即。 self.current_image - 您将在下一个过滤器中使用它。 也许你应该学会使用self.而不是global 【参考方案1】:

坦率地说,我不明白你为什么会遇到问题。

每个过滤器都应该将图像分配给全局/类变量,即。 self.current_img

def Gaussian_filter(self, img):

    # ... code ...

    self.current_img = img_smooth
    self.reshow_image(self.current_img)

def Sobel_filter(self, img):

    # ... code ...

    self.current_img = sobel
    self.reshow_image(self.current_img)


def Prewitt_filter(self, img):

    # ... code ...

    self.current_img = Prewitt
    self.reshow_image(self.current_img)

每个过滤器都应该使用来自这个变量self.current_img的图像

    Canny_action.triggered.connect(
        lambda : self.Canny_filter(self.current_img)
    )

    Sobel_action.triggered.connect(
        lambda: self.Sobel_filter(self.current_img)
    )

    Prewitt_action.triggered.connect(
        lambda : self.Prewitt_filter(self.current_img)
    )

    Gaussian_action.triggered.connect(
        lambda : self.Gaussian_filter(self.current_img)
    )

    Canny_action.triggered.connect(
        lambda : self.Canny_filter(self.current_img)
    )

    LoG_action.triggered.connect(
        lambda : self.LoG_filter(self.current_img)
    )

开始阅读时也是这样

    if file_name[0] != '': # is not '':
        img = cv2.imread(file_name[0])

        self.current_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.original_img = self.current_img.copy()

        self.reshow_image(self.current_img)

如果我想从原始图像开始,我还使用self.original_img 来保留原始图像。


编辑

使用类变量self.current_img,您甚至可以直接在方法中使用它——无需作为参数发送。

Canny_action.triggered.connect(self.Canny_filter)
Sobel_action.triggered.connect(self.Sobel_filter)
Prewitt_action.triggered.connect(self.Prewitt_filter)
Gaussian_action.triggered.connect(self.Gaussian_filter)
Canny_action.triggered.connect(self.Canny_filter)
LoG_action.triggered.connect(self.LoG_filter)

def Gaussian_filter(self):

    img = self.current_img    

    # ... code ...

    self.current_img = img_smooth
    self.reshow_image(self.current_img)

def Sobel_filter(self):

    img = self.current_img    

    # ... code ...

    self.current_img = sobel
    self.reshow_image(self.current_img)


def Prewitt_filter(self):

    img = self.current_img    

    # ... code ...

    self.current_img = Prewitt
    self.reshow_image(self.current_img)

顺便说一句:

def reset_to_original_image(self):

    self.current_img = self.original_img.copy()

    self.reshow_image(self.current_img)

顺便说一句:

您甚至可以创建包含所有图像历史记录的列表

def Sobel_filter(self):

    self.history.append(self.current_img.copy())
 
    img = self.current_img    

    # ... code ...

    self.current_img = sobel
    self.reshow_image(self.current_img)

编辑:

完整的工作代码。

过滤器作用于前一个过滤器的结果。

你还有Reset to original image的功能。

所有图像都被记录在历史中,您可以使用Undo 函数返回到上一个图像。你甚至可以撤消Reset

import sys
import numpy as np
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import cv2

class Ui_MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()

        self.init_Main_Ui()
        self.init_Menu_Ui()

        self.current_img = None  # default value at start
        self.original_img = None # default value at start

        self.history = []

    def init_Main_Ui(self):
        self.setObjectName("test")
        self.setEnabled(True)
        self.resize(1200, 700)
        self.setMinimumSize(QtCore.QSize(500, 300))
        self.setMaximumSize(QtCore.QSize(500, 300))

        self.image_label = QLabel(self)

        self.setCentralWidget(self.image_label)

        self.show()

    def init_Menu_Ui(self):

        menu_bar = self.menuBar()
        menu_bar.setNativeMenuBar(False)

        file_menu = menu_bar.addMenu('&File')  # &가 alt+F 메뉴 단축키 지정

        Exit_action = QAction('Exit', self)
        Exit_action.setShortcut('Ctrl+Q')
        Exit_action.triggered.connect(qApp.quit)

        Open_action = QAction('open', self)
        Open_action.setShortcut('Ctrl+O')
        Open_action.triggered.connect(self.read_file)

        file_menu.addAction(Open_action)
        file_menu.addAction(Exit_action)

        self.filter_menu = menu_bar.addMenu("&Filter")
        self.filter_menu.setEnabled(False)

        Reset_action = QAction('Reset to original image', self)
        Reset_action.setShortcut('Alt+0')
        Reset_action.triggered.connect(self.reset_to_original_image)

        Sobel_action = QAction('Sobel filter', self)
        Sobel_action.setShortcut('Alt+1')
        Sobel_action.triggered.connect(self.Sobel_filter)

        Prewitt_action = QAction('Prewitt filter', self)
        Prewitt_action.setShortcut('Alt+2')
        Prewitt_action.triggered.connect(self.Prewitt_filter)

        Gaussian_action = QAction('Gaussian filter', self)
        Gaussian_action.setShortcut('Alt+3')
        Gaussian_action.triggered.connect(self.Gaussian_filter)

        Canny_action = QAction('Canny filter', self)
        Canny_action.setShortcut('Alt+4')
        Canny_action.triggered.connect(self.Canny_filter)  # filter has to exist

        LoG_action = QAction('LoG filter', self)
        LoG_action.setShortcut('Alt+5')
        LoG_action.triggered.connect(self.LoG_filter)  # filter has to exist

        Undo_action = QAction('Undo filter', self)
        Undo_action.setShortcut('Alt+X')
        Undo_action.triggered.connect(self.Undo_filter)  # filter has to exist
        
        self.setWindowTitle('Image Processing')
        self.filter_menu.addAction(Reset_action)
        self.filter_menu.addAction(Sobel_action)
        self.filter_menu.addAction(Prewitt_action)
        self.filter_menu.addAction(Gaussian_action)

        self.filter_menu.addAction(Undo_action)

    def read_file(self):
        file_name = QFileDialog.getOpenFileName(self)

        if file_name[0] != '': # is not '':
            img = cv2.imread(file_name[0])

            self.original_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            self.current_img = self.original_img.copy()

            self.reshow_image(self.current_img)
            self.filter_menu.setEnabled(True)
        else:
            print('please put img')

    def save_image(self):
        print("save")

    def reset_to_original_image(self):
        self.history.append(self.current_img.copy())
        self.current_img = self.original_img.copy()
        self.reshow_image(self.current_img)

    def Sobel_filter(self):

        self.history.append(self.current_img.copy())

        img = self.current_img

        cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

        sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
        sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)

        sobel = img.copy()
        height = np.size(img, 0)
        width = np.size(img, 1)

        for i in range(width):
            for j in range(height):
                sobel[j, i] = np.minimum(255, np.round(np.sqrt(sobelx[j, i] * sobelx[j, i] + sobely[j, i] * sobely[j, i])))

        sobel = cv2.cvtColor(sobel, cv2.COLOR_GRAY2RGB)
        cv2.imwrite("Sobel Filtered Image.png", sobel)

        self.current_img = sobel
        self.reshow_image(self.current_img)

    def Prewitt_filter(self):

        self.history.append(self.current_img.copy())

        img = self.current_img

        img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

        kernelx = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]])
        kernely = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])

        img_prewittx = cv2.filter2D(img, -1, kernelx)
        img_prewitty = cv2.filter2D(img, -1, kernely)

        Prewitt = cv2.cvtColor(img_prewittx + img_prewitty, cv2.COLOR_GRAY2RGB)

        self.current_img = Prewitt
        self.reshow_image(self.current_img)

    def Gaussian_filter(self):

        self.history.append(self.current_img.copy())

        img = self.current_img

        img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        img_smooth = cv2.GaussianBlur(img, (3, 3), 0)
        img_smooth = cv2.cvtColor(img_smooth, cv2.COLOR_GRAY2RGB)

        self.current_img = img_smooth
        self.reshow_image(self.current_img)

    def Canny_filter(self):
        print("TODO: create Canny_filter")
        #self.history.append(self.current_img.copy())
        #img = self.current_img
        # ... code ... 
        #self.current_img = img_smooth
        #self.reshow_image(self.current_img)

    def LoG_filter(self):
        print("TODO: create LoG_filter")
        #self.history.append(self.current_img.copy())
        #img = self.current_img
        # ... code ... 
        #self.current_img = img_smooth
        #self.reshow_image(self.current_img)

    def Undo_filter(self):
        if self.history:
            self.current_img = self.history.pop(-1)
            self.reshow_image(self.current_img)

    def reshow_image(self, cv_img):
        if cv_img is not None:
            self.image_label.resize(cv_img.shape[1], cv_img.shape[0])
            Q_img = QImage(cv_img.data, cv_img.shape[1], cv_img.shape[0], cv_img.shape[1] * 3, QImage.Format_RGB888)
            self.image_label.setPixmap(QPixmap.fromImage(Q_img))
        else:
            print("Image load failed")


    def exit(self):
        cv2.waitKey(0)
        cv2.destroyAllWindows()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    ui = Ui_MainWindow()
    sys.exit(app.exec_())

【讨论】:

非常感谢!你的回答很有帮助!

以上是关于如何将第一个处理图像(例如 Canny 过滤器)的输出作为另一个处理过滤器的输入?的主要内容,如果未能解决你的问题,请参考以下文章

图像经过Canny算子处理后如何获取边缘位置的像素坐标

MATLAB中的Canny算子矩阵:如何实现/获取? (只是过滤器,没有边缘检测器)

OpenCV中的图像处理 —— 图像梯度+Canny边缘检测+图像金字塔

图像处理之Canny边缘检测

六 OpenCV图像处理4 Canny 边缘检测

图像处理:推导Canny边缘检测算法