opencv之图像变换

人工智能 2025-04-17 10:15:17
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


class ImageProcessing:
    def __init__(self, image_path):
        self.image_path = image_path
        self.img = cv.imread(self.image_path)
        if self.img is None:
            raise FileNotFoundError(f"无法读取图像文件: {self.image_path}")

    def numpy_fourier_transform(self):
        """
        使用Numpy进行傅里叶变换,并展示结果
        """
        img_gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)
        f = np.fft.fft2(img_gray)
        fshift = np.fft.fftshift(f)
        magnitude_spectrum = 20 * np.log(np.abs(fshift))

        plt.subplot(1, 2, 1), plt.imshow(img_gray, cmap='gray')
        plt.title('Input Image'), plt.xticks([]), plt.yticks([])
        plt.subplot(1, 2, 2), plt.imshow(magnitude_spectrum, cmap='gray')
        plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
        plt.show()

        rows, cols = img_gray.shape
        crow, ccol = rows // 2, cols // 2
        fshift[crow - 30:crow + 31, ccol - 30:ccol + 31] = 0
        f_ishift = np.fft.ifftshift(fshift)
        img_back = np.fft.ifft2(f_ishift)
        img_back = np.real(img_back)

        plt.subplot(1, 3, 1), plt.imshow(img_gray, cmap='gray')
        plt.title('Input Image'), plt.xticks([]), plt.yticks([])
        plt.subplot(1, 3, 2), plt.imshow(img_back, cmap='gray')
        plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
        plt.subplot(1, 3, 3), plt.imshow(img_back)
        plt.title('Result in JET'), plt.xticks([]), plt.yticks([])
        plt.show()

    def opencv_fourier_transform(self):
        """
        使用OpenCV进行傅里叶变换,并展示结果
        """
        img_gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)
        dft = cv.dft(np.float32(img_gray), flags=cv.DFT_COMPLEX_OUTPUT)
        dft_shift = np.fft.fftshift(dft)
        magnitude_spectrum = 20 * np.log(cv.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))

        plt.subplot(1, 2, 1), plt.imshow(img_gray, cmap='gray')
        plt.title('Input Image'), plt.xticks([]), plt.yticks([])
        plt.subplot(1, 2, 2), plt.imshow(magnitude_spectrum, cmap='gray')
        plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
        plt.show()

        rows, cols = img_gray.shape
        crow, ccol = rows // 2, cols // 2
        mask = np.zeros((rows, cols, 2), np.uint8)
        mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 1

        fshift = dft_shift * mask
        f_ishift = np.fft.ifftshift(fshift)
        img_back = cv.idft(f_ishift)
        img_back = cv.magnitude(img_back[:, :, 0], img_back[:, :, 1])

        plt.subplot(1, 2, 1), plt.imshow(img_gray, cmap='gray')
        plt.title('Input Image'), plt.xticks([]), plt.yticks([])
        plt.subplot(1, 2, 2), plt.imshow(img_back, cmap='gray')
        plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
        plt.show()

    def show_filters(self):
        """
        展示不同滤波器的频域响应
        """
        img_gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)

        # 没有缩放参数的简单均值滤波器
        mean_filter = np.ones((3, 3))
        # 创建高斯滤波器
        x = cv.getGaussianKernel(5, 10)
        gaussian = x * x.T
        # 不同的边缘检测滤波器
        # x方向上的scharr
        scharr = np.array([[-3, 0, 3],
                           [-10, 0, 10],
                           [-3, 0, 3]])
        # x方向上的sobel
        sobel_x = np.array([[-1, 0, 1],
                            [-2, 0, 2],
                            [-1, 0, 1]])
        # y方向上的sobel
        sobel_y = np.array([[-1, -2, -1],
                            [0, 0, 0],
                            [1, 2, 1]])
        # 拉普拉斯变换
        laplacian = np.array([[0, 1, 0],
                              [1, -4, 1],
                              [0, 1, 0]])

        filters = [mean_filter, gaussian, laplacian, sobel_x, sobel_y, scharr]
        filter_name = ['mean_filter', 'gaussian', 'laplacian','sobel_x',
                       'sobel_y','scharr_x']
        fft_filters = [np.fft.fft2(x) for x in filters]
        fft_shift = [np.fft.fftshift(y) for y in fft_filters]
        mag_spectrum = [np.log(np.abs(z) + 1) for z in fft_shift]

        for i in range(6):
            plt.subplot(2, 3, i + 1), plt.imshow(mag_spectrum[i], cmap='gray')
            plt.title(filter_name[i]), plt.xticks([]), plt.yticks([])
        plt.show()

    def template_matching(self, template_path):
        """
        进行模板匹配,并展示不同方法的结果
        :param template_path: 模板图像的路径
        """
        img_gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)
        template = cv.imread(template_path, 0)
        if template is None:
            raise FileNotFoundError(f"无法读取模板图像文件: {template_path}")

        w, h = template.shape[::-1]
        methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
                   'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']

        for meth in methods:
            img = img_gray.copy()
            method = eval(meth)
            res = cv.matchTemplate(img, template, method)
            min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)

            if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:
                top_left = min_loc
            else:
                top_left = max_loc
            bottom_right = (top_left[0] + w, top_left[1] + h)
            cv.rectangle(img, top_left, bottom_right, 255, 2)

            plt.subplot(1, 2, 1), plt.imshow(res, cmap='gray')
            plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
            plt.subplot(1, 2, 2), plt.imshow(img, cmap='gray')
            plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
            plt.suptitle(meth)
            plt.show()

    def multi_object_template_matching(self, template_path, threshold=0.8):
        """
        进行多对象的模板匹配,并保存结果图像
        :param template_path: 模板图像的路径
        :param threshold: 匹配阈值,默认为0.8
        """
        img_rgb = self.img.copy()
        img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
        template = cv.imread(template_path, 0)
        if template is None:
            raise FileNotFoundError(f"无法读取模板图像文件: {template_path}")

        w, h = template.shape[::-1]
        res = cv.matchTemplate(img_gray, template, cv.TM_CCOEFF_NORMED)
        loc = np.where(res >= threshold)
        for pt in zip(*loc[::-1]):
            cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
        cv.imwrite('res.png', img_rgb)

    def hough_line_transform(self):
        """
        进行霍夫线变换,并保存结果图像
        """
        img = self.img.copy()
        gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
        edges = cv.Canny(gray, 50, 150, apertureSize=3)
        lines = cv.HoughLines(edges, 1, np.pi / 180, 200)

        for line in lines:
            rho, theta = line[0]
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a * rho
            y0 = b * rho
            x1 = int(x0 + 1000 * (-b))
            y1 = int(y0 + 1000 * (a))
            x2 = int(x0 - 1000 * (-b))
            y2 = int(y0 - 1000 * (a))
            cv.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
        cv.imwrite('houghlines3.jpg', img)

    def probabilistic_hough_line_transform(self):
        """
        进行概率霍夫线变换,并保存结果图像
        """
        img = self.img.copy()
        gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
        edges = cv.Canny(gray, 50, 150, apertureSize=3)
        lines = cv.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength=100, maxLineGap=10)

        for line in lines:
            x1, y1, x2, y2 = line[0]
            cv.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
        cv.imwrite('houghlines5.jpg', img)

    def hough_circle_transform(self):
        """
        进行霍夫圈变换,并展示结果
        """
        img_gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)
        img_gray = cv.medianBlur(img_gray, 5)
        cimg = cv.cvtColor(img_gray, cv.COLOR_GRAY2BGR)
        circles = cv.HoughCircles(img_gray, cv.HOUGH_GRADIENT, 1, 20,
                                   param1=50, param2=30, minRadius=0, maxRadius=0)

        if circles is not None:
            circles = np.uint16(np.around(circles))
            for i in circles[0, :]:
                # 绘制外圆
                cv.circle(cimg, (i[0], i[1]), i[2], (0, 255, 0), 2)
                # 绘制圆心
                cv.circle(cimg, (i[0], i[1]), 2, (0, 0, 255), 3)

            cv.imshow('detected circles', cimg)
            cv.waitKey(0)
            cv.destroyAllWindows()

    def watershed_segmentation(self):
        """
        进行图像分割与Watershed算法
        """
        img = self.img.copy()
        gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
        ret, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)

        # 噪声去除
        kernel = np.ones((3, 3), np.uint8)
        opening = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel, iterations=2)
        # 确定背景区域
        sure_bg = cv.dilate(opening, kernel, iterations=3)
        # 寻找前景区域
        dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5)
        ret, sure_fg = cv.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
        # 找到未知区域
        sure_fg = np.uint8(sure_fg)
        unknown = cv.subtract(sure_bg, sure_fg)

        # 类别标记
        ret, markers = cv.connectedComponents(sure_fg)
        # 为所有的标记加1,保证背景是0而不是1
        markers = markers + 1
        # 现在让所有的未知区域为0
        markers[unknown == 255] = 0

        markers = cv.watershed(img, markers)
        img[markers == -1] = [255, 0, 0]

        cv.imshow('Segmented Image', img)
        cv.waitKey(0)
        cv.destroyAllWindows()

    def grabcut_foreground_extraction(self, rect=(50, 50, 450, 290), new_mask_path=None):
        """
        使用GrabCut算法进行交互式前景提取
        :param rect: 初始矩形框,默认为(50, 50, 450, 290)
        :param new_mask_path: 新掩码图像的路径,如果为None则不使用新掩码,默认为None
        """
        img = self.img.copy()
        mask = np.zeros(img.shape[:2], np.uint8)
        bgdModel = np.zeros((1, 65), np.float64)
        fgdModel = np.zeros((1, 65), np.float64)

        cv.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv.GC_INIT_WITH_RECT)
        mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
        img = img * mask2[:, :, np.newaxis]

        plt.imshow(img), plt.colorbar(), plt.show()

        if new_mask_path is not None:
            newmask = cv.imread(new_mask_path, 0)
            mask[newmask == 0] = 0
            mask[newmask == 255] = 1
            mask, bgdModel, fgdModel = cv.grabCut(img, mask, None, bgdModel, fgdModel, 5, cv.GC_INIT_WITH_MASK)
            mask = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
            img = img * mask[:, :, np.newaxis]
            plt.imshow(img), plt.colorbar(), plt.show()
...全文
116 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

4

社区成员

发帖
与我相关
我的任务
社区描述
学习交流人工智能相关算法及技术栈
opencv计算机视觉人工智能 技术论坛(原bbs) 广东省·深圳市
社区管理员
  • 亿只小灿灿
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧