前言
仅记录学习过程,有问题欢迎讨论
边缘提取(涉及语义分割):
图象的边缘是指图象局部区域亮度变化显著的部分,也有正负之分,暗到亮为正
-
求边缘的幅度:sobel,Canny算子
-
图像分高频分量和低频分量,高频分量就是灰度变化剧烈的地方(显眼)
图像锐化:目的是使图像的边缘更加清晰,细节部分更加突出,常用拉普拉斯变化核函数。
边缘检测的步骤:边缘检测就是提取高频分量。在边缘像素值会出现”跳跃“或者较大的变化
- 滤波:边缘检测的算法主要是基于图像强度的一阶和二阶导数(为0,一阶极值),但导数通常对噪声很敏感,
所以采用滤波减弱噪声。常见的滤波方法主要有高斯滤波。 - 增强:增强边缘的基础是确定图像各点邻域强度的变化值并凸显出显著变化点。
- 检测:经过增强的图像,往往邻域中有很多点的梯度值比较大,可以采用用阈值化方法来检测方法来对这些点进行取舍。
Canny边缘检测算法:
- 灰度化后高斯滤波:消除噪声
高斯卷积核大小影响Canny检测的性能,越大,检测对噪声敏感越低,定位误差也会增大,5*5还行 - 检测图像的水平/垂直边缘:计算梯度—Sobel算子
用类似于[-1,0,1][-2,0,2][-1,0,1]的矩阵来求梯度的幅值,幅值较大的像素点的为边缘 - 非极大值抑制:去除边缘检测带来的杂散响应
- 搜素局部最大值,抑制非极大值,去除冗余的边缘。通俗就是找到像素局部最大值,其他值置为0,就可以剔除大部分非边缘点。
- 沿着梯度方向比较像素点的值,保留最大像素点
- 双阈值检测和连接边缘:滞后阈值法
- 大于高阈值为强边缘,小于低阈值不是边缘。介于中间是弱边缘。
- 阈值的选择取决于给定输入图像的内容,和噪声点的区别就是是否连续:
相机模型(实际就是坐标系转化):
针孔相机模型存在四个坐标系:世界坐标系、摄像机坐标系、图像物理坐标系和图像像素坐标系。
- 世界坐标系的坐标为Pw(Xw,Yw,Zw),
- 对应的摄像机坐标系坐标为Po(x,y,z),–齐次方程做坐标系变化
- 对应的图像物理坐标系的坐标为P’(x’,y’),–相似三角的原理等比例
- 对应的图像像素坐标系的坐标为p(u,v)。–转化为长度为像素单位!
镜头畸变
- 畸变是由于透镜形状和制造工艺的误差造成的,分为径向畸变和切向畸变。
- 径向畸变是由于透镜形状的曲线造成,分为枕形畸变和桶形畸变。
- 切向畸变是由于透镜制造工艺的误差造成的,分为对称畸变和非对称畸变。
- 可以通过透视变化(投影为新平面)来矫正畸变图片
通过4个点(两组x,y)来确定关系,然后投影新平面图片
Canny算法和透视变化
"""
1-实现canny算法
2-实现透视变换
"""
import cv2
import numpy as np
# 实现Canny
def CannyDemo(img, low, high):
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯滤波
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# 采用sobel 算子求梯度[x,y方向求梯度,找出变化最大的像素点]
grad_x = cv2.Sobel(blur, cv2.CV_16S, 1, 0, ksize=3)
grad_y = cv2.Sobel(blur, cv2.CV_16S, 0, 1, ksize=3)
# 转回uint8
abs_grad_x = cv2.convertScaleAbs(grad_x)
abs_grad_y = cv2.convertScaleAbs(grad_y)
# 合并梯度
dst = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
# 非极大值抑制
dst = cv2.Canny(dst, low, high)
return dst
# 实现透视变化
def getWarpPerspectiveMatrix(img, dst):
nums = img.shape[0]
x = np.zeros((2 * nums, 8)) # x*warpMatrix=y
y = np.zeros((2 * nums, 1))
for i in range(0, nums):
x_i = src[i, :]
y_i = dst[i, :]
x[2 * i, :] = [x_i[0], x_i[1], 1, 0, 0, 0,
-x_i[0] * y_i[0], -x_i[1] * y_i[0]]
y[2 * i] = y_i[0]
x[2 * i + 1, :] = [0, 0, 0, x_i[0], x_i[1], 1,
-x_i[0] * y_i[1], -x_i[1] * y_i[1]]
y[2 * i + 1] = y_i[1]
x = np.mat(x)
# 用x.I求出x的逆矩阵,然后与y相乘,求出warpMatrix
matrix = x.I * y # 求出a_11, a_12, a_13, a_21, a_22, a_23, a_31, a_32
# 之后为结果的后处理
matrix = np.array(matrix).T[0]
matrix = np.insert(matrix, matrix.shape[0], values=1.0, axis=0) # 插入a_33 = 1
matrix = matrix.reshape((3, 3))
return matrix
if __name__ == '__main__':
img = cv2.imread('lenna.png')
# canny边缘检测
# canny = CannyDemo(img, 50,150)
# cv2.imshow('canny', canny)
# cv2.waitKey(0)
# 实现透视变化
img1 = cv2.imread('photo1.jpg')
src = np.float32([[207, 151], [517, 285], [17, 601], [343, 731]])
dst = np.float32([[0, 0], [337, 0], [0, 488], [337, 488]])
print(img.shape)
# 生成透视变换矩阵;进行透视变换
result = getWarpPerspectiveMatrix(src, dst)
print("warpMatrix:")
print(result)
img_perspective = cv2.warpPerspective(img1, result, (337, 488))
cv2.imshow("img_perspective", img_perspective)
cv2.waitKey(0)