zoukankan      html  css  js  c++  java
  • 数字图像处理-基本算法的代码实现(基于OpenCV)

    1. RGB图像灰度化

    • 分量法

      将彩色图像中的三分量的亮度作为三个灰度图像的灰度值,可根据应用需要选取一种灰度图像。

    • 最大值法

      将彩色图像中的三分量亮度的最大值作为灰度图的灰度值。

    • 平均值法

      将彩色图像中的三分量亮度求平均得到一个灰度值。

    • 加权平均法

      根据重要性及其它指标,将三个分量以不同的权值进行加权平均。由于人眼对绿色的敏感最高,对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到较合理的灰度图像。

    2. 二值化

    import cv2
    import numpy as np
    
    # Read image
    img = cv2.imread("imori.jpg").astype(np.float)
    b = img[:, :, 0].copy()
    g = img[:, :, 1].copy()
    r = img[:, :, 2].copy()
    
    # Grayscale
    out = 0.2126 * r + 0.7152 * g + 0.0722 * b
    out = out.astype(np.uint8)
    
    # Binarization
    th = 128
    out[out < th] = 0
    out[out >= th] = 255
    
    # Save result
    cv2.imwrite("out.jpg", out)
    cv2.imshow("result", out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    3. OSTU: 大津二值化算法

    Opencv大津二值化算法

    最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津
    法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差
    越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部
    分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

    也就是说:

    import cv2
    import numpy as np
    
    # Read image
    img = cv2.imread("imori.jpg").astype(np.float)
    
    H, W, C = img.shape
    
    # Grayscale
    out = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0]
    out = out.astype(np.uint8)
    
    # Determine threshold of Otsu's binarization
    max_sigma = 0
    max_t = 0
    
    for _t in range(1, 255):
        v0 = out[np.where(out < _t)]
        m0 = np.mean(v0) if len(v0) > 0 else 0.
        w0 = len(v0) / (H * W)
        v1 = out[np.where(out >= _t)]
        m1 = np.mean(v1) if len(v1) > 0 else 0.
        w1 = len(v1) / (H * W)
        sigma = w0 * w1 * ((m0 - m1) ** 2)
        if sigma > max_sigma:
            max_sigma = sigma
            max_t = _t
    
    # Binarization
    print("threshold >>", max_t)
    th = max_t
    out[out < th] = 0
    out[out >= th] = 255
    
    # Save result
    cv2.imwrite("out.jpg", out)
    cv2.imshow("result", out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    4. Pooling: 最大池化

    # Max Pooling
    out = img.copy()
    
    H, W, C = img.shape
    G = 8
    Nh = int(H / G)
    Nw = int(W / G)
    
    for y in range(Nh):
        for x in range(Nw):
            for c in range(C):
                out[G*y:G*(y+1), G*x:G*(x+1), c] = np.max(out[G*y:G*(y+1), G*x:G*(x+1), c])
    

    5. 高斯滤波

    高斯滤波器是一种可以使图像平滑的滤波器,用于去除噪声。可用于去除噪声的滤波器还有中值滤波器,平滑滤波器、LoG 滤波器。

    高斯滤波器将中心像素周围的像素按照高斯分布加权平均进行平滑化。这样的(二维)权值通常被称为卷积核或者滤波器。

    但是,由于图像的长宽可能不是滤波器大小的整数倍,因此我们需要在图像的边缘补0。这种方法称作 Zero Padding。并且权值(卷积核)要进行归一化操作 ( ∑g=1 )。

    权值 g(x,y,s) = 1/ (s*sqrt(2 * pi)) * exp( - (x^2 + y^2) / (2*s^2))
    标准差 s = 1.3 的 8 近邻 高斯滤波器如下:
                 1 2 1
    K = 1/16 * [ 2 4 2 ]
                 1 2 1
    

    代码实现:

    # Gaussian Filter
    K_size = 3
    sigma = 1.3
    
    ## 6. Zero padding
    pad = K_size // 2
    out = np.zeros((H + pad*2, W + pad*2, C), dtype=np.float)
    out[pad:pad+H, pad:pad+W] = img.copy().astype(np.float)
    
    ## 7. Kernel
    K = np.zeros((K_size, K_size), dtype=np.float)
    for x in range(-pad, -pad+K_size):
        for y in range(-pad, -pad+K_size):
            K[y+pad, x+pad] = np.exp( -(x**2 + y**2) / (2* (sigma**2)))
    
    K /= (sigma * np.sqrt(2 * np.pi))
    K /= K.sum()
    
    tmp = out.copy()
    
    for y in range(H):
        for x in range(W):
            for c in range(C):
                out[pad+y, pad+x, c] = np.sum(K * tmp[y:y+K_size, x:x+K_size, c])
    
    out = out[pad:pad+H, pad:pad+W].astype(np.uint8)
    

    8. 最邻近插值

    Opencv最邻近插值

    使用最邻近插值将图像放大1.51.5倍吧!

    Opencv最近邻插值在图像放大时补充的像素取最临近的像素的值。由于方法简单,所以处理速度很快,但是放大图像画质劣化明显。

    使用下面的公式放大图像吧!I’I’为放大后图像,II为放大前图像,aa为放大率,方括号是四舍五入取整操作:

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    # Nereset Neighbor interpolation
    def nn_interpolate(img, ax=1, ay=1):
        H, W, C = img.shape
    
        aH = int(ay * H)
        aW = int(ax * W)
    
        y = np.arange(aH).repeat(aW).reshape(aW, -1)
        x = np.tile(np.arange(aW), (aH, 1))
        y = np.round(y / ay).astype(np.int)
        x = np.round(x / ax).astype(np.int)
    
        out = img[y,x]
        out = out.astype(np.uint8)
        return out
    
    # Read image
    img = cv2.imread("imori.jpg").astype(np.float)
    
    # Nearest Neighbor
    out = nn_interpolate(img, ax=1.5, ay=1.5)
    

    9. Canny边缘检测

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    def Canny_step1(img):
        # Gray scale
        def BGR2GRAY(img):
            ...
        def gaussian_filter(img, K_size=3, sigma=1.3):
            ...
        def sobel_filter(img, K_size=3):
            ...
    
        def get_edge_angle(fx, fy):
            # get edge strength
            edge = np.sqrt(np.power(fx, 2) + np.power(fy, 2))
            # fx[np.abs(fx) < 1e-5] = 1e-5
            fx = np.maximum(fx, 1e-5)
            angle = np.arctan(fy / fx)
            return edge, angle
    
        def angle_quantization(angle):
            angle = angle / np.pi * 180
            angle[angle < -22.5] = 180 + angle[angle < -22.5]
            _angle = np.zeros_like(angle, dtype=np.uint8)
            _angle[np.where(angle <= 22.5)] = 0
            _angle[np.where((angle > 22.5) & (angle <= 67.5))] = 45
            _angle[np.where((angle > 67.5) & (angle <= 112.5))] = 90
            _angle[np.where((angle > 112.5) & (angle <= 157.5))] = 135
            return _angle
    
        gray = BGR2GRAY(img)
        gaussian = gaussian_filter(gray, K_size=5, sigma=1.4)
        fy, fx = sobel_filter(gaussian, K_size=3)
        edge, angle = get_edge_angle(fx, fy)
        angle = angle_quantization(angle)
        return edge, angle
    
    # Read image
    img = cv2.imread("imori.jpg").astype(np.float32)
    
    # Canny (step1)
    edge, angle = Canny_step1(img)
    
    edge = edge.astype(np.uint8)
    angle = angle.astype(np.uint8)
    
    # Save result
    cv2.imwrite("out.jpg", edge)
    cv2.imshow("result", edge)
    cv2.imwrite("out2.jpg", angle)
    cv2.imshow("result2", angle)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    10. Hough Transform: 霍夫变换

    霍夫变换,是将座标由直角座标系变换到极座标系,然后再根据数学表达式检测某些形状(如直线和圆)的方法。当直线上的点变换到极座标中的时候,会交于一定的rr、tt的点。这个点即为要检测的直线的参数。通过对这个参数进行逆变换,我们就可以求出直线方程。

    方法如下:

    1. 我们用边缘图像来对边缘像素进行霍夫变换。
    2. 在霍夫变换后获取值的直方图并选择最大点。
    3. 对极大点的r和t的值进行霍夫逆变换以获得检测到的直线的参数。

    在这里,进行一次霍夫变换之后,可以获得直方图。算法如下:

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    def Canny(img):
        def BGR2GRAY(img):
            # Gray scale
        def gaussian_filter(img, K_size=3, sigma=1.3):
            # Gaussian filter for grayscale
        def sobel_filter(img, K_size=3):
            # sobel filter
        def get_edge_angle(fx, fy):
            # 同上
        def angle_quantization(angle):
            # 同上
        def non_maximum_suppression(angle, edge):
            H, W = angle.shape
            _edge = edge.copy()
    
            for y in range(H):
                for x in range(W):
                    if angle[y, x] == 0:
                            dx1, dy1, dx2, dy2 = -1, 0, 1, 0
                    elif angle[y, x] == 45:
                            dx1, dy1, dx2, dy2 = -1, 1, 1, -1
                    elif angle[y, x] == 90:
                            dx1, dy1, dx2, dy2 = 0, -1, 0, 1
                    elif angle[y, x] == 135:
                            dx1, dy1, dx2, dy2 = -1, -1, 1, 1
                    if x == 0:
                            dx1 = max(dx1, 0)
                            dx2 = max(dx2, 0)
                    if x == W-1:
                            dx1 = min(dx1, 0)
                            dx2 = min(dx2, 0)
                    if y == 0:
                            dy1 = max(dy1, 0)
                            dy2 = max(dy2, 0)
                    if y == H-1:
                            dy1 = min(dy1, 0)
                            dy2 = min(dy2, 0)
                    if max(max(edge[y, x], edge[y + dy1, x + dx1]), edge[y + dy2, x + dx2]) != edge[y, x]:
                            _edge[y, x] = 0
            return _edge
    
        def hysterisis(edge, HT=100, LT=30):
            H, W = edge.shape
    
            # Histeresis threshold
            edge[edge >= HT] = 255
            edge[edge <= LT] = 0
    
            _edge = np.zeros((H + 2, W + 2), dtype=np.float32)
            _edge[1 : H + 1, 1 : W + 1] = edge
    
            ## 8 - Nearest neighbor
            nn = np.array(((1., 1., 1.), (1., 0., 1.), (1., 1., 1.)), dtype=np.float32)
    
            for y in range(1, H+2):
                    for x in range(1, W+2):
                            if _edge[y, x] < LT or _edge[y, x] > HT:
                                    continue
                            if np.max(_edge[y-1:y+2, x-1:x+2] * nn) >= HT:
                                    _edge[y, x] = 255
                            else:
                                    _edge[y, x] = 0
    
            edge = _edge[1:H+1, 1:W+1]
            return edge
    
        gray = BGR2GRAY(img)
        gaussian = gaussian_filter(gray, K_size=5, sigma=1.4)
        fy, fx = sobel_filter(gaussian, K_size=3)
        edge, angle = get_edge_angle(fx, fy)
        angle = angle_quantization(angle)
        edge = non_maximum_suppression(angle, edge)
        out = hysterisis(edge, 100, 30)
        return out
    
    def Hough_Line_step1(edge):
        ## Voting
        def voting(edge):
            H, W = edge.shape
            drho = 1
            dtheta = 1
            # get rho max length
            rho_max = np.ceil(np.sqrt(H ** 2 + W ** 2)).astype(np.int)
            # hough table
            hough = np.zeros((rho_max * 2, 180), dtype=np.int)
            # get index of edge
            ind = np.where(edge == 255)
            ## hough transformation
            for y, x in zip(ind[0], ind[1]):
                for theta in range(0, 180, dtheta):
                        # get polar coordinat4s
                        t = np.pi / 180 * theta
                        rho = int(x * np.cos(t) + y * np.sin(t))
                        # vote
                        hough[rho + rho_max, theta] += 1
    
            out = hough.astype(np.uint8)
            return out
    
        out = voting(edge)
        return out
    
    # Read image
    img = cv2.imread("thorino.jpg").astype(np.float32)
    edge = Canny(img)
    out = Hough_Line_step1(edge)
    
    out = out.astype(np.uint8)
    
    # Save result
    cv2.imwrite("out.jpg", out)
    cv2.imshow("result", out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    11. Hessian角点检测

    Opencv Hessian角点检测

  • 相关阅读:
    从boosting谈起
    《人月神话》读书摘记
    Python中input()的使用方法
    Web前端攻击方式及防御措施
    吞吐量(TPS)、QPS、并发数、响应时间(RT)概念
    Mybatis的Mapper文件sql语句中使用常量值或者枚举常量值
    Java依据文件头获取文件类型
    MySQL查询优化
    RabbitMQ学习教程
    SpringBoot2.x.x + Shiro + Redis 前后端分离实现
  • 原文地址:https://www.cnblogs.com/brt2/p/14206224.html
Copyright © 2011-2022 走看看