OpenCV学习之图像的基础处理

目录

一、在图像上绘制图形
二、获取一点像素值以及修改一点像素值
 三、获取图片的大小
四、通道的拆分与组合
五、转换颜色空间:RGB→Gray和RGB→HSV
六、图像的算数运算
七、图像的混合
八、图像的缩放
九、图像平移
十、图像旋转
十一、仿射变化的矩阵
十二、透射变换
十三、图像金字塔
十四、连通性
十五、开闭运算
十六、礼帽和黑帽
十七、均值滤波
十八、高斯滤波
十九、中值滤波
二十、灰度直方图
二十一、掩膜的应用
二十二、直方图均衡化
二十三、自适应的直方图均衡化
二十四、边缘检测(Sobel检测算子)
二十五、 边缘检测(Laplacian算子)
二十六、边缘检测(Canny检测)
二十七、模板匹配
二十八、霍夫变换
二十九、角点特征
三十、SIFT算法

一、在图像上绘制图形

import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']


# 创建图像
img = np.zeros((512, 512, 3), np.uint8)

# 绘制图形
cv.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
cv.circle(img, (256, 256), 60, (0, 0, 255), -1)
cv.rectangle(img, (100, 100), (400, 400), (0, 255, 0), 5)
cv.putText(img, "Hello", (70, 500), cv.FONT_HERSHEY_DUPLEX, 5, (255, 255, 255), 3)

# 显示结果
plt.imshow(img[:, :, ::-1])
plt.show()

二、获取一点像素值以及修改一点像素值

import numpy as np
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']


# 创建10*10的图像
img = np.full((10, 10, 3), (0, 0, 0), np.uint8)

# 获取某一个点的像素值
px = img[5, 5]
print(px)

# 仅获取蓝色通道的强度值
blue = img[5, 5, 0]
print(blue)

# 修改某个位置的像素值
img[5, 5] = [0, 255, 0]

# 展示图像
plt.imshow(img[:, :, ::-1])
plt.show()

 三、获取图片的大小

import cv2 as cv

# 导入图像
img = cv.imread('square.jpg')

shape = img.shape
t = img.dtype
size = img.size
print(shape, t, size)

四、通道的拆分与组合

import cv2 as cv
import matplotlib.pyplot as plt

# 导入图像
img = cv.imread('square.jpg')

# 通道拆分(显示b通道的灰度图)
b, g, r = cv.split(img)
plt.imshow(b, cmap=plt.cm.gray)
plt.show()

# 通道合并
img = cv.merge((b, g, r))

五、转换颜色空间:RGB→Gray和RGB→HSV

import cv2 as cv
import matplotlib.pyplot as plt

# 导入图像
img = cv.imread('square.jpg')

# 转换RGB→Gray
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
plt.imshow(gray, cmap=plt.cm.gray)
plt.show()

#  转换RGB→HSV
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
plt.imshow(hsv)
plt.show()

六、图像的算数运算

import cv2 as cv
import matplotlib.pyplot as plt

# 1、读取两张图像
square = cv.imread('square.jpg')
flag = cv.imread('flag.jpg')

# 2、两张图像分别用opencv加法和直接相加的的方法进行操作
img1 = cv.add(square, flag)
img2 = square + flag

# 3、图像显示
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img1[:, :, ::-1])
axes[0].set_title("cv中的加法")
axes[1].imshow(img2[:, :, ::-1])
axes[1].set_title("直接相加")
plt.show()

七、图像的混合

import cv2 as cv
import matplotlib.pyplot as plt

# 1、读取两张图像
square = cv.imread('square.jpg')
flag = cv.imread('flag.jpg')

# 2、图像混合
img = cv.addWeighted(square, 0.7, flag, 0.3, 0)

# 3、图像显示
plt.figure(figsize=(8, 8))
plt.imshow(img[:, :, ::-1])
plt.show()

八、图像的缩放

'''API: cv.resize(src, dsize,fx=0,fy=0,interpolation=cv2.INTER_LINEAR
        参数:
        src:输入图像
        dsize:绝对尺寸,直接是定调整后的图像大小
        fx,fy:相对尺寸,将dsize设定为None,然后将fx和fy设定为比例因子即可
        interpolation:插值方法,主要有以下四种:
            cv2.INTER_LINEAR    双线性插值法
            cv2.INTER_NEAREST   最近邻插值法
            cv2.INTER_AREA      像素区域采样(默认)
            cv2.INTER_CUBIC     双三次插值法'''


import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']


# 1、导入图像
img = cv.imread('square.jpg')

# 2.图像缩放
# 2.1绝对尺寸
rows, cols = img.shape[:2]
res = cv.resize(img, (2*cols, 2*rows), interpolation=cv.INTER_CUBIC)

# 2.2相对尺寸
res1 = cv.resize(img, None, fx=0.5, fy=0.5)

# 3.图像显示
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(10, 8), dpi=100)
axes[0].imshow(res[:, :, ::-1])
axes[0].set_title("绝对尺寸(放大)")
axes[1].imshow(img[:, :, ::-1])
axes[1].set_title("原图")
axes[2].imshow(res1[:, :, ::-1])
axes[2].set_title("相对尺寸(缩小)")
plt.show()

九、图像平移

'''API:     cv.warpAffine(img, M, dsize)
        参数:
        img:输入图像
        M:2*3移动矩阵
            对于(x,y)处的像素点,要把他移动到(x+tx,y+ty)处时,M矩阵应该如下设置:
            M=[1,0,tx ;0,1,ty;    ] 注意需要将M设置为np.float32类型的Numpy数组
        dsize:输出图像大小    (宽度*高度)的形式
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

# 1.输入图像
img = cv.imread('square.jpg')

# 2.图像平移
rows, cols = img.shape[:2]
M = M = np.float32([[1, 0, 500], [0, 1, 500]])
dst = cv.warpAffine(img, M, (cols, rows))

# 3.图像显示
fig, axes= plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img[:, :, ::-1])
axes[0].set_title("原图")
axes[1].imshow(dst[:, :, ::-1])
axes[1].set_title("移动后的图像")
plt.show()

十、图像旋转

'''
    API:    cv2.getRotationMatrix2D(center, angle, scale)
    参数:
    center:旋转中心
    angle:旋转角度
    scale:缩放比例
        返回:M:旋转矩阵
    调用cv.warpAffine完成图像的旋转
        
'''


import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']


# 1.导入图像
img = cv.imread('square.jpg')

# 2.图像旋转
rows, cols = img.shape[:2]
# 2.1生成旋转矩阵
M = cv.getRotationMatrix2D((cols/2, rows/2), 90, 1)
# 2.2进行旋转变换
dst = cv.warpAffine(img, M, (cols, rows))

# 3图像展示
fig, axes=plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img[:, :, ::-1])
axes[0].set_title("原图")
axes[1].imshow(dst[:, :, ::-1])
axes[1].set_title("旋转后的结果")
plt.show()

十一、仿射变化的矩阵


import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

# 1.图像读取
img = cv.imread('square.jpg')

# 2.仿射变换
rows, cols = img.shape[:2]

# 2.1创建变换矩阵
pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
pts2 = np.float32([[100, 100], [200, 50], [100, 250]])
M = cv.getAffineTransform(pts1, pts2)

# 2.2 完成仿射变换
dst = cv.warpAffine(img, M, (cols, rows))

# 3.图像展示
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img[:, :, ::-1])
axes[0].set_title("原图")
axes[1].imshow(dst[:, :, ::-1])
axes[1].set_title("仿射后的图像")
plt.show()

十二、透射变换

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']


# 1.图像读取
img = cv.imread('square.jpg')

# 2.仿射变换
rows, cols = img.shape[:2]

# 2.1创建变换矩阵
pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
pts2 = np.float32([[100, 145], [300, 100], [80, 290], [310, 310]])
T = cv.getPerspectiveTransform(pts1, pts2)

# 2.2 进行变换
dst = cv.warpPerspective(img, T, (cols, rows))

# 3.图像展示
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img[:, :, ::-1])
axes[0].set_title("原图")
axes[1].imshow(dst[:, :, ::-1])
axes[1].set_title("透射后的图像")
plt.show()

十三、图像金字塔

'''
    API:cv.pyrUp(img)       #对图像进行上采样
        cv.pyrDown(img)     #对图像进行上采样
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

# 1.图像读取
img = cv.imread('square.jpg')

# 2.对图像进行上采样
up_img = cv.pyrUp(img)
down_img = cv.pyrDown(img)

# 3.图像显示

cv.imshow('enlarge', up_img)
cv.imshow('original', img)
cv.imshow('shrink', down_img)
cv.waitKey(0)
cv.destroyAllWindows()

十四、连通性

'''
    连通性的条件:1.两个像素位置相邻
               2.两个像素的灰度值满足特定的相似性准则
腐蚀和膨胀
    1.腐蚀
        API: cv.erode(img, kernel, iterations)
        参数:
        img:要处理的图像
        kernel:核结构
        iterations:腐蚀的次数,默认为1
    2.膨胀
        API:cv.dilate(img, kernel, iterations)
        参数:img:要处理的图像
            kernel:核结构
            iterations:腐蚀的次数

'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

# 1读取图像
img = cv.imread('square.jpg')

# 2创建核结构
kernel = np.ones((5, 5), np.uint8)

# 3图像的腐蚀与膨胀
erosion = cv.erode(img, kernel)
dilate = cv.dilate(img, kernel)

# 4图像展示
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(10, 8), dpi=100)
axes[0].imshow(img)
axes[0].set_title('原图')
axes[1].imshow(erosion)
axes[1].set_title('腐蚀后的图像')
axes[2].imshow(dilate)
axes[2].set_title('膨胀后的图像')
plt.show()

十五、开闭运算

'''
    1.开运算:
        定义:先腐蚀后膨胀
        作用:分离物体,消除小区域
        特点:消除噪点,去除小的干扰块,而不影响原来的图像
    2.闭运算
        定义:先膨胀后腐蚀
        作用:消除/“闭合”物体里面的孔洞
        特点:可以填充闭合区域
    API: 
        cv.morphologyEx(img, op, kernel)
        参数:
        img:要处理的图像
        op:处理的方式:若进行开运算,则设为cv.MORPH_OPEN
                     若进行闭运算,则设为cv.MORPH_CLOSE
        kernel:核结构
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

# 1导入图像
img1 = cv.imread('square.jpg')
img2 = cv.imread('flag.jpg')

# 2创建核结构
kernel = np.ones((10, 10), np.uint8)

# 3图像的开闭
cvOpen = cv.morphologyEx(img1, cv.MORPH_OPEN, kernel)
cvClose = cv.morphologyEx(img2, cv.MORPH_CLOSE, kernel)

# 4图像展示
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8))
axes[0, 0].imshow(img1)
axes[0, 0].set_title("原图")
axes[0, 1].imshow(cvOpen)
axes[0, 1].set_title("开运算结果")
axes[1, 0].imshow(img2)
axes[1, 0].set_title("原图")
axes[1, 1].imshow(cvClose)
axes[1, 1].set_title("闭运算结果")
plt.show()

十六、礼帽和黑帽

'''
    1.礼帽运算
        原图像与开运算结果图之差
        公式:dst= tophat(src,element)=src- open(src,element)
    2.黑帽运算
        闭运算的结果图与原图像之差
        公式:dst= blackhat(src,element)= close(src,element)-src
    API: cv.morphologyEx(img, op, kernel)
        参数:
        img:处理的图像
        op:处理方式
            cv.MORPH_CLOSE      闭运算
            cv.MORPH_OPEN       开运算
            cv.MORPH_TOPHAT     礼帽运算
            cv.MORPH_BLACKHAT   黑帽运算
        kernel:核结构
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

# 1导入图像
img1 = cv.imread('square.jpg')
img2 = cv.imread('flag.jpg')

# 2创建核结构
kernel = np.ones((10, 10), np.uint8)

# 3图像的礼帽与黑帽运算
cvOpen = cv.morphologyEx(img1, cv.MORPH_TOPHAT, kernel)
cvClose = cv.morphologyEx(img2, cv.MORPH_BLACKHAT, kernel)

# 4图像展示
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8))
axes[0, 0].imshow(img1)
axes[0, 0].set_title("原图")
axes[0, 1].imshow(cvOpen)
axes[0, 1].set_title("礼帽结果")
axes[1, 0].imshow(img2)
axes[1, 0].set_title("原图")
axes[1, 1].imshow(cvClose)
axes[1, 1].set_title("黑帽结果")
plt.show()

十七、均值滤波

'''
    优点:算法简单,计算速度快
    缺点:去噪的同时会去除很多细节部分,将图像变得模糊
    API:    cv.blur(src, ksize, anchor, borderType)
    参数:src:输入图像
        ksize:卷积核的大小
        anchor:默认值(-1, -1),表示核中心
        borderType:边界类型
'''
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

# 1.导入图像
img = cv.imread('square.jpg')

# 2.均值滤波
blur = cv.blur(img, (5, 5))

# 3.图像显示
plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(img[:, :, ::-1]), plt.title("原图")
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(blur[:, :, ::-1]),plt.title("均值滤波之后的结果")
plt.xticks([]), plt.yticks([])
plt.show()

十八、高斯滤波

'''
    API: cv.GaussianBlur(src, ksize, sigmaX, sigmay, borderType)
    参数:
        src:输入图像
        ksize:高斯卷积核大小,注意:卷积核的宽度和高度都应该是奇数,且可以不同
        sigmaX:水平方向的标准差
        sigmaY:垂直方向的标准差,默认为0,表示与sigmaX相同
        borderType:填充边界类型
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('square.jpg')

blur = cv.GaussianBlur(img, (3, 3), 1)

plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(img[:, :, ::-1]), plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(blur[:, :, ::-1]), plt.title('高斯滤波之后的图像')
plt.xticks([]), plt.yticks([])
plt.show()

十九、中值滤波

'''
    API:    cv.medianBlur(src, ksize)
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

# 1.导入图像
img = cv.imread('square.jpg')

# 2.中值滤波
blur = cv.medianBlur(img, 5)

# 3.图像显示
plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(img[:, :, ::-1]), plt.title("原图")
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(blur[:, :, ::-1]), plt.title("中值滤波之后的结果")
plt.xticks([]), plt.yticks([])
plt.show()

二十、灰度直方图

'''
    API: cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
    参数:
        images:原图。当传入函数时应该用中括号[]括起来
        Channels:如果输入的是灰度图,他的值就是[0],如果是彩色的话,传入的参数可以是[0],[1],[2]它们分别对应着通道BGR
        mask:掩膜图像。要统计整幅直方图就把他设置为None。统计某一部分的话需要制作一个研掩膜图像
        histSize:BIN的数目,用[]括起来
        ranges:像素值范围,通常为[0, 256]    
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

# 1.导入图像
img = cv.imread('square.jpg', 0)

# 2.统计灰度图
histr = cv.calcHist([img], [0], None, [256], [0, 256])

plt.figure(figsize=(10, 6), dpi=100)
plt.plot(histr)
plt.grid()
plt.show()

二十一、掩膜的应用

'''
    掩膜是由0和1组成的一个二进制图像。通常使用二维矩阵数组进行。其中1值区域被处理,0值区域被屏蔽
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('square.jpg', 0)
# 创建蒙版
mask = np.zeros(img.shape[:2], np.uint8)
mask[400:1650, 200:1500] = 255
# 掩膜
masked_img = cv.bitwise_and(img, img, mask=mask)
# 统计掩膜后图像的灰度图
mask_histr = cv.calcHist([img], [0], mask, [256], [1, 256])

fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8))
axes[0, 0].imshow(img, cmap=plt.cm.gray)
axes[0, 0].set_title('原图')
axes[0, 1].imshow(mask, cmap=plt.cm.gray)
axes[0, 1].set_title('蒙版数据')
axes[1, 0].imshow(masked_img, cmap=plt.cm.gray)
axes[1, 0].set_title('掩膜后数据')
axes[1, 1].plot(mask_histr)
axes[1, 1].grid()
axes[1, 1].set_title('灰度直方图')
plt.show()

二十二、直方图均衡化

'''
    API: dst = cv.equalizeHist(img)
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('square.jpg', 0)

dst = cv.equalizeHist(img)

fig, axes= plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img, cmap=plt.cm.gray)
axes[0].set_title('原图')
axes[1].imshow(dst, cmap=plt.cm.gray)
axes[1].set_title('均衡化后的结果')
plt.show()

二十三、自适应的直方图均衡化

'''
    整幅图像会被分成很多小块,这些小块被称为“tiles”(默认大小为8*8)。然后对每一小块分别进行直方图均衡化
    API : cv.createCLAHE(clipLimit, tileGridSize)
    参数:
    clipLimit:对比度限制,默认为40
    tileGridSize:分块的大小,默认为8*8
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('square.jpg', 0)

clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
cl1 = clahe.apply(img)

fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img, cmap=plt.cm.gray)
axes[0].set_title('原图')
axes[1].imshow(cl1, cmap=plt.cm.gray)
axes[1].set_title('自适应均衡化之后的结果')
plt.show()

二十四、边缘检测(Sobel检测算子)

'''
    (1)Sobel检测算子
    API:Sobel_x_or_y = cv2.Sobel(src, ddepth, dx, dy, dst, ksize, scale, delta, borderType)
    参数: 
        src:传入的图像
        ddepth:图像的深度
        dx和dy:只求导的阶数,0表示在这个方向上没有求导,取值为0,、1
        ksize:是Sobel算子的大小,即卷积核的大小,必须为奇数,默认为3
        scale:缩放导数的比例常数,默认情况下没有伸缩系数
        borderType:图像边界的模式,默认为cv2.BORDER_DEFAULT
    注意:Sobel函数求完导数之后会有负值,还会有大于255的值,而原图像是uint8,即8位无符号数,所有Sobel建立的图像位数不够,会有截断
        现象。因此要使用16位有符号的数据类型,即cv2.CV_16S。处理完成后,再使用cv2.convertScaleAbs()函数将其转换成原来的uint8格式,否则无法显示
    Sobel算子是在两个方向上计算的,最后还需要用cv2.addWeighted()函数将其组合起来
        Scale_abs = cv2.convertScaleAbs(x)
        result = cv2.addWeighted(src1, alpha, src2,beta)
'''
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('square.jpg', 0)
# 计算Sobel卷积结果
x = cv.Sobel(img, cv.CV_16S, 1, 0)
y = cv.Sobel(img, cv.CV_16S, 0, 1)
# 将数据进行转换
Scale_absX = cv.convertScaleAbs(x)
Scale_absY = cv.convertScaleAbs(y)
# 结果合成
result = cv.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
# 图像显示
plt.figure(figsize=(10, 8), dpi=80)
plt.subplot(121), plt.imshow(img, cmap=plt.cm.gray), plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(result, cmap=plt.cm.gray), plt.title('Sobel滤波之后的结果')
plt.xticks([]), plt.yticks([])
plt.show()

二十五、 边缘检测(Laplacian算子)

'''
    (2)Laplacian算子
        拉普拉斯算子,用二阶导数
        API: laplacian = cv2.Laplacian(src, ddepth[, dst[,ksize[, scale[, delta[, borderType]]]]])
        
'''
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('square.jpg', 0)
# laplacian转换
result = cv.Laplacian(img, cv.CV_16S)
Scale_abs = cv.convertScaleAbs(result)
# 图像显示
plt.figure(figsize=(10, 8), dpi=80)
plt.subplot(121), plt.imshow(img, cmap=plt.cm.gray), plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(Scale_abs, cmap=plt.cm.gray), plt.title('Laplacian检测之后的结果')
plt.xticks([]), plt.yticks([])
plt.show()

二十六、边缘检测(Canny检测)

'''
    (3)Canny检测
        API: canny = cv2.Canny(image, threshold1, threshold2)
        参数:
            image:灰度图
            threshold1:minval,较小的阈值将间断的边缘连接起来
            threshold2:maxval,较大的阈值检测图像中明显的边缘
'''
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('square.jpg', 0)
# Canny边缘检测
lowThreshold = 0
max_lowThreshold = 100
canny = cv.Canny(img, lowThreshold, max_lowThreshold)
# 图像显示
plt.figure(figsize=(10, 8), dpi=80)
plt.subplot(121), plt.imshow(img, cmap=plt.cm.gray), plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(canny, cmap=plt.cm.gray), plt.title('Canny检测之后的结果')
plt.xticks([]), plt.yticks([])
plt.show()

二十七、模板匹配

'''
    定义:在给定的图片中查找和模板最相似的区域
    API:res = cv.matchTemplate(img, template, method)
        参数:img:要进行模板匹配的图像
            Template:模板
            method:实现模板匹配的算法,主要有
                    1、平方差匹配(CV_TM_SQDIFF):主要利用模板与图像之间的平方差进行匹配,最好的匹配是0,匹配越差,匹配的值越大
                    2、相关匹配(CV_TM_CCORR):利用模板与图像之间的乘法进行匹配,数值越大表示匹配程度越高,反之匹配程度较小
                    3、利用相关系数匹配(CV_TM_CCOEFF):利用模板与图像之间的相关系数匹配,1表示完美的匹配,-1表示最差的匹配
            匹配完成后,使用cv.minMaxLoc()方法查找最大值所在的位置即可。如果要使用平方差作为比较方法,则最小位置是最佳匹配位置
'''
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('square.jpg')
template = cv.imread('square_template.jpg')
h, w, l = template.shape
# 模板匹配
res = cv.matchTemplate(img, template, cv.TM_CCORR)
# 返回图像中最匹配的位置,确定左上角的坐标,并将匹配位置绘制在图像上
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)

top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv.rectangle(img, top_left, bottom_right, (0, 0, 0), 2)
# 图像显示
plt.imshow(img[:, :, ::-1])
plt.title('匹配结果'), plt.xticks([]), plt.yticks([])
plt.show()

二十八、霍夫变换

'''
    定义:用来提取图像中的直线和圆等几何形状
    1、霍夫线变换
    在笛卡尔坐标系中一条直线由两个点确定
    笛卡尔坐标系中的一条直线,对应于霍夫空间中的一个点
    API:cv.HoughLines(img, rho, theta, threshold)
    参数:
        img:检测的图像,要求是二值化的图像,所以在调用霍夫变换之前首先要进行二值化,或者进行Canny边缘检测
        rho、theta:ρ和θ的精确度
        threshold::阈值,只有累加器中的值高于该阈值时才被认为是直线
'''

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('line.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 150)
# 霍夫直线变换
lines = cv.HoughLines(edges, 0.8, np.pi / 180, 150)
# 将检测的线绘制在图像上
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, 255, 0))
plt.figure(figsize=(10, 8), dpi=100)
plt.imshow(img[:, :, ::-1]), plt.title('霍夫变换线检测')
plt.xticks([]), plt.yticks([])
plt.show()

'''
    霍夫圆变换
    API:circles = cv.HoughCircles(img, method, dp, minDist, param1=100, param2=100, minRadius=0, maxRadius=0)
    参数:
        img:输入图像
        method:使用霍夫变换圆检测的算法,他的参数是CV_HOUGH_GRASIENT
        dp: 霍夫空间的分辨率,dp=1时表示霍夫空间与输入图像空间的大小一致,dp=2时霍夫空间是输入图像空间的一半
        minDist:为圆心之间的最小距离,如果检测到两个圆心之间距离小于该值,则认为它们是同一个圆心
        param1:边缘检测时使用Canny算子的高阈值,低阈值时高阈值的一半 
        param2:检测圆心和确定半径时所共有的阈值
        minRadius和maxRadius为所检测到的圆半径的最小值与最大值
    返回:
        circles:输出圆向量,包括三个浮点型的元素——圆心横坐标,圆心纵坐标和圆半径
    由于霍夫圆检测对噪声比较敏感,所以首先对图像进行中值滤波
'''
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

planets = cv.imread('line.jpg')
gay_img = cv.cvtColor(planets, cv.COLOR_BGRA2GRAY)
# 进行中值模糊
img = cv.medianBlur(gay_img, 7)
# 霍夫圆检测
circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1, 200, param1=100, param2=30, minRadius=0, maxRadius=100)

for i in circles[0, :]:
    cv.circle(planets, (i[0], i[1]), i[2], (0, 255, 0), 2)
    cv.circle(planets, (i[0], i[1]), 2, (0, 0, 255), 3)
plt.figure(figsize=(10, 8), dpi=100)
plt.imshow(planets[:, :, ::-1]), plt.title('霍夫变换圆检测')
plt.xticks([]), plt.yticks([])
plt.imshow()

二十九、角点特征

'''
    1、Harris角点检测
    思想:通过图像的局部的小窗口观察图像,角点的特征是窗口沿任意方向移动都会导致图像灰度的明显变化
    API : dst = cv.cornerHarris(src, blockSize, ksize, k)
        参数:
            img:数据类型为float32的输入图像
            blockSize:角点检测中要考虑的邻域大小
            kszie:sobel求导使用的核大小
            k:角点检测方程中的自由参数,取值为[0.04, 0.06]
'''
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('square.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 角点检测
gray = np.float32(gray)
dst = cv.cornerHarris(gray, 2, 3, 0.04)
img[dst>0.001*dst.max()] = [0, 0, 225]

plt.figure(figsize=(10, 8), dpi=100)
plt.imshow(img[:, :, ::-1]), plt.title('Harris角点检测')
plt.xticks([]), plt.yticks([])
plt.show()
'''
2、Shi-Tomasi角点检测
    API : corners = cv2.goodFeaturesToTrack(image, maxcorners, qualityLevel, minDistance)
    参数:
        Image:输入灰度图像
        maxCorners:获取角点数的数目
        qualityLevel:该参数指出最低可接受的角点质量水平。在0-1之间
        minDistance:角点之间最小的欧式距离,避免得到相邻的特征点
    返回:
        corners:搜索到的角点,在这里所有低于质量水平的角点被排除掉,然后把合格的角点按质量排序,然后将质量较好的角点附近(小于最小欧氏距离)的角点删掉,最后找到maxcorners个角点返回
        
'''
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from pylab import mpl

# matpltotlib 绘图时正常显示字体
mpl.rcParams['font.sans-serif'] = ['SimHei']

img = cv.imread('line.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

corners = cv.goodFeaturesToTrack(gray, 10, 0.02, 20)

for i in corners:
    x, y = i.ravel()
    cv.circle(img, (x, y), 2, (0, 0, 255), -1)

plt.figure(figsize=(10, 8), dpi=100)
plt.imshow(img[:, :, ::-1]), plt.title('Shi-Tomasi角点检测')
plt.xticks([]), plt.yticks([])
plt.show()

三十、SIFT算法

'''
    分解为四步:
        1、尺度空间极值检测:搜索所有尺度上的图像位置。通过高斯差分函数来识别潜在的对于尺度和旋转不变的关键点
        2、关键点定位:在每一个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于他们的稳定程度
        3、关键点方向确定:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像的数据操作 都相对于关键点的
        方向、尺度和位置进行变换,从而保证了对于这些变换的不变性。
        4、关键点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度作为关键点的描述符,它允许比较大的局部形状的变形或者光照的变化
    改进:SURF算法
        计算量小,运算速度快
    代码实现SIFT算法
        1、实例化sift
            sift = cv.xfeatures2d.SIFT_create()
        2、利用sift.detectAndCompute()检测关键点并计算
            kp, des = sift.detectAndCompute(gray,None)
            参数:
            gray:进行关键点检测的图像,要用灰度图像
            返回:
            kp:关键点信息,包括位置,尺度,方向信息
            des:关键点描述符,每个关键点对应128个梯度信息的特征向量
        3、将关键点检测结果绘制在图像上
            cv.drawKeypoints(image, keypoints, outputimage, color, flags)
            参数:
            Image:原始图像
            keypoints:关键点信息,将其绘制在图像上
            outputimage:输出图片,可以是原始图像
            color:颜色设置,通过修改RGB的值
            flags:绘图功能的标识设置
                ①cv2.DRAW_MATCHES_FLAGS_DEFAULT:创建输出图像矩阵,使用现存的输出图像绘制匹配对和特征点,对每一个关键点只绘制中间点
                ②cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG:不创建输出图像,而是在输出图像上绘制匹配对
                ③cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS:对每一个特征点绘制带大小和方向的关键点图形
                ④cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制
'''
img = cv.imread('square.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
sift = cv.SIFT_create()
kp, des = sift.detectAndCompute(gray, None)
cv.drawKeypoints(img, kp, img, flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
plt.figure(figsize=(10, 8), dpi=100)
plt.imshow(img[:, :, ::-1]), plt.title('sift检测')
plt.xticks([]), plt.yticks([])
plt.show()

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咸鱼翻身的路上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值