forked from iwater2018/badou-ai-special-2024
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7257121
commit c30fab5
Showing
5 changed files
with
296 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
import numpy as np | ||
import matplotlib.pyplot as plt | ||
import math | ||
|
||
if __name__ == "__main__": | ||
pic_path = "lenna.png" | ||
img = plt.imread(pic_path) | ||
print("样本集img\n",img) | ||
if pic_path[-4:] == ".png": # [-4:] 切片,截取倒数第4位至最后一位 | ||
# .png图片在这里的存储格式是0到1的浮点数,所以要扩展到255再计算 | ||
img = img * 255 # 还是浮点数类型 | ||
img = img.mean(axis = -1) # 取均值的方法进行灰度化 | ||
print("样本集img灰度化\n", img) | ||
|
||
# 1.高斯平滑 | ||
# sigma = 1.52 高斯平滑时的高斯核参数,标准差,可调 | ||
sigma = 0.5 | ||
dim = 5 # 高斯核尺寸 | ||
Gaussion_filter = np.zeros([dim,dim]) # 储存高斯核,这是数组,不是列表 | ||
tmp = [i - dim//2 for i in range(dim)] # 生成一个序列 | ||
print("tmp:",tmp) | ||
# 计算高斯核,公式:n1为e左侧数据,n2为e的指数数据。math.pi:圆周率π | ||
n1 = 1/(2 * math.pi * sigma**2) | ||
n2 = -1/(2 * sigma**2) | ||
for i in range(dim): | ||
for j in range(dim): # math.exp:e的幂次方 | ||
Gaussion_filter[i,j] = n1 * math.exp(n2*(tmp[i]**2 + tmp[j]*22)) | ||
# 1)归一化后加快了梯度下降求最优解的速度;2)归一化有可能提高精度(如KNN) | ||
Gaussion_filter = Gaussion_filter / Gaussion_filter.sum() # 归一化 | ||
|
||
dx,dy = img.shape # 获取原图的行列数 | ||
print("dx:",dx,"\ndy:",dy) | ||
img_new = np.zeros(img.shape) # 储存平滑后的图像,zeros函数得到的是浮点型数据 | ||
""" np.pad()图像边缘填充技术, | ||
即在图像四周边缘填充0,使得卷积运算后图像大小不会缩小,同时也不会丢失边缘和角落的信息 | ||
在卷积神经网络中,通常采用constant填充方式""" | ||
r = dim//2 # 高斯核半径为2 | ||
img_pad = np.pad(img,((r,r),(r,r)),"constant") | ||
for i in range(dx): | ||
for j in range(dy): | ||
img_new[i,j] = np.sum(img_pad[i:i+dim,j:j+dim] * Gaussion_filter) | ||
plt.figure(1) | ||
plt.imshow(img_new.astype(np.uint8),cmap="gray") # 此时的img_new是255的浮点型数据,强制类型转换才可以,gray灰阶 | ||
plt.axis("off") | ||
# plt.show() | ||
|
||
# 2、求梯度。以下两个是滤波用的sobel矩阵(检测图像中的水平、垂直和对角边缘) | ||
sobel_kernel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) | ||
sobel_kernel_y = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]]) | ||
img_tidu_x = np.zeros(img_new.shape) | ||
img_tidu_y = np.zeros([dx,dy]) | ||
img_tidu = np.zeros(img_new.shape) | ||
img_pad = np.pad(img_new,((1,1),(1,1)),"constant") | ||
for i in range(dx): | ||
for j in range(dy): | ||
img_tidu_x[i,j] = np.sum(img_pad[i:i+3,j:j+3]*sobel_kernel_x) # X方向 | ||
img_tidu_y[i,j] = np.sum(img_pad[i:i+3,j:j+3]*sobel_kernel_y) # Y方向 | ||
img_tidu[i,j] = np.sqrt(img_tidu_x[i,j]**2 + img_tidu_y[i,j]**2) | ||
img_tidu_x[img_tidu_x == 0] = 0.000000001 | ||
tan = img_tidu_y/img_tidu_x | ||
print("tan:\n",tan) | ||
plt.figure(2) | ||
plt.imshow(img_tidu.astype(np.uint8),cmap="gray") | ||
plt.axis("off") | ||
# plt.show() | ||
|
||
# 3、非极大值抑制 | ||
img_yizhi = np.zeros(img_tidu.shape) | ||
print("img_yizhi:\n",img_yizhi) | ||
for i in range(1,dx - 1): # 没有做np.pad 所以边缘像素点要去掉 | ||
for j in range(1,dy - 1): # 没有做np.pad 所以边缘像素点要去掉 | ||
flag = True # 在8个邻域内是否要抹去做个标记 | ||
temp = img_tidu[i-1:i+2, j-1:j+2] # 梯度幅值的8邻域矩阵 | ||
if tan[i,j] <= -1: | ||
num_1 = (temp[0,1] - temp[0,0])/tan[i,j] + temp[0,1] | ||
num_2 = (temp[2,1] - temp[2,2])/tan[i,j] + temp[2,1] | ||
if not (img_tidu[i,j] > num_1 and img_tidu[i, j] > num_2): | ||
flag = False | ||
elif tan[i,j] >= 1: | ||
num_1 = (temp[0,2] - temp[0,1])/tan[i,j] + temp[0,1] | ||
num_2 = (temp[2,0] - temp[2,1])/tan[i,j] + temp[2,1] | ||
if not (img_tidu[i, j] > num_1 and img_tidu[i, j] > num_2): | ||
flag = False | ||
elif tan[i,j] > 0: | ||
num_1 = (temp[0,2] - temp[1,2])/tan[i,j] + temp[1,2] | ||
num_2 = (temp[2,0] - temp[1,0])/tan[i,j] + temp[1,0] | ||
if not (img_tidu[i, j] > num_1 and img_tidu[i, j] > num_2): | ||
flag = False | ||
elif tan[i,j]: | ||
num_1 = (temp[1,0] - temp[0,0])/tan[i,j] + temp[1,0] | ||
num_2 = (temp[1,2] - temp[2,2])/tan[i,j] + temp[1,2] | ||
if not (img_tidu[i, j] > num_1 and img_tidu[i, j] > num_2): | ||
flag = False | ||
if flag: | ||
img_yizhi[i,j] = img_tidu[i,j] | ||
print("img_yizhi后:\n", img_yizhi) | ||
plt.figure(3) | ||
plt.imshow(img_yizhi.astype(np.uint8),cmap="gray") | ||
plt.axis("off") | ||
# plt.show() | ||
|
||
# 4、双阈值检测,链接边缘。遍历所有一定是边的点,查看8邻域是否存在可能是边的点 | ||
lower_boundary = img_tidu.mean() * 0.5 | ||
high_boundary = lower_boundary * 3 | ||
zhan = [] | ||
for i in range(1,img_yizhi.shape[0]-1): # 外圈不考虑了 | ||
for j in range(1,img_yizhi.shape[1]-1): | ||
if img_yizhi[i,j] >= high_boundary: # 大于高阈值为强边缘,留 | ||
img_yizhi[i,j] = 255 | ||
zhan.append([i,j]) | ||
elif img_yizhi[i,j] <= lower_boundary: # 小于低阈值不是边缘 | ||
img_yizhi[i,j] = 0 | ||
|
||
while not len(zhan) == 0: | ||
temp_1,temp_2 = zhan.pop() | ||
a = img_yizhi[temp_1-1:temp_1+2, temp_2-1:temp_2+2] | ||
print("a:\n",a) | ||
""" | ||
小于高阈值并且大于低阈值为弱边缘,弱化边缘周围8邻域有强边缘,则保留为真是边缘, | ||
逆向思考,强边缘的8邻域周围有弱边缘,则保留该弱边缘,记录为强边缘 | ||
""" | ||
if (a[0, 0] < high_boundary) and (a[0, 0] > lower_boundary): | ||
img_yizhi[temp_1 - 1, temp_2 - 1] = 255 # 这个像素点标记为边缘 | ||
zhan.append([temp_1 - 1, temp_2 - 1]) # 进栈 | ||
if (a[0, 1] < high_boundary) and (a[0, 1] > lower_boundary): | ||
img_yizhi[temp_1 - 1, temp_2] = 255 | ||
zhan.append([temp_1 - 1, temp_2]) | ||
if (a[0, 2] < high_boundary) and (a[0, 2] > lower_boundary): | ||
img_yizhi[temp_1 - 1, temp_2 + 1] = 255 | ||
zhan.append([temp_1 - 1, temp_2 + 1]) | ||
if (a[1, 0] < high_boundary) and (a[1, 0] > lower_boundary): | ||
img_yizhi[temp_1, temp_2 - 1] = 255 | ||
zhan.append([temp_1, temp_2 - 1]) | ||
if (a[1, 2] < high_boundary) and (a[1, 2] > lower_boundary): | ||
img_yizhi[temp_1, temp_2 + 1] = 255 | ||
zhan.append([temp_1, temp_2 + 1]) | ||
if (a[2, 0] < high_boundary) and (a[2, 0] > lower_boundary): | ||
img_yizhi[temp_1 + 1, temp_2 - 1] = 255 | ||
zhan.append([temp_1 + 1, temp_2 - 1]) | ||
if (a[2, 1] < high_boundary) and (a[2, 1] > lower_boundary): | ||
img_yizhi[temp_1 + 1, temp_2] = 255 | ||
zhan.append([temp_1 + 1, temp_2]) | ||
if (a[2, 2] < high_boundary) and (a[2, 2] > lower_boundary): | ||
img_yizhi[temp_1 + 1, temp_2 + 1] = 255 | ||
zhan.append([temp_1 + 1, temp_2 + 1]) | ||
|
||
# 经过强边缘检测完毕后,要么为0,要么为255。还有不在强边缘周边的点,均定义为非边缘。 | ||
for i in range(img_yizhi.shape[0]): | ||
for j in range(img_yizhi.shape[1]): | ||
if img_yizhi[i,j] != 0 and img_yizhi[i,j] != 255: | ||
img_yizhi[i,j] = 0 | ||
plt.figure(4) | ||
plt.imshow(img_yizhi.astype(np.uint8),cmap='gray') | ||
plt.axis('off') | ||
plt.show() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# encoding = UTF-8 | ||
|
||
import cv2 | ||
import numpy as np | ||
|
||
""" | ||
cv2.Canny(image, threshold1, threshold2,[,edges[,aperureSize[,L2gradient ]]]) | ||
必要参数: | ||
第一个参数是需要处理的原图像,该图像必须为单通道的灰度图; | ||
第二个参数是阈值1; | ||
第三个参数是阈值2。 | ||
""" | ||
|
||
img = cv2.imread("lenna.png",1) # 1是彩色图 bgr # 0是灰度图 | ||
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) | ||
cv2.imshow("canny",cv2.Canny(gray,50,150)) | ||
cv2.waitKey() | ||
cv2.destroyAllWindows() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# encoding = UTF-8 | ||
|
||
''' | ||
Canny边缘检测:优化的程序 | ||
''' | ||
|
||
import cv2 | ||
import numpy as np | ||
|
||
def CannyThreshold(lowThreshold): | ||
# detected_edges = cv2.GaussianBlur(gray,(3,3),0) # 高斯滤波 | ||
detected_edges = cv2.Canny(gray, | ||
lowThreshold, | ||
lowThreshold * ratio, | ||
apertureSize = kernel_size) # 边缘检测,apertureSize默认是5 | ||
# 用原始颜色添加到检测的边缘上 | ||
# 按位“与”操作。对每个像素,将两幅输入图像相应位置的像素值分别进行按位“与”运算,输出的结果图像的对应项数值即为这两幅输入图像对应像素值按位 与 结果 | ||
# src1和src2表示要进行按位“与”操作的两幅输入图像; | ||
# mask 是可选参数,如果指定了掩膜,则只对掩膜对应位置的像素进行按位“与”操作,函数的返回值表示按位“与”运算的结果 | ||
dst = cv2.bitwise_and(img,img,mask= detected_edges) | ||
cv2.imshow('canny result',dst) | ||
cv2.waitKey() | ||
|
||
lowThreshold = 0 # 低阈值 | ||
max_lowThreshold = 100 # max低阈值 | ||
ratio = 3 | ||
kernel_size = 3 # kernel大小为:3*3 | ||
|
||
img = cv2.imread("lenna.png") # 读图 | ||
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 转灰度 | ||
|
||
cv2.namedWindow('canny result') # cv2.namedWindow创建一个窗口 | ||
|
||
# 设置调节杆 | ||
""" | ||
下面是第二个函数,cv2.createTrackbar() | ||
共有5个参数,其实这五个参数看变量名就大概能知道是什么意思 | ||
第一个参数,是这个trackbar对象的名字 | ||
第二个参数,是这个trackbar对象所在面板的名字 | ||
第三个参数,是这个trackbar的默认值,也是调节的对象 | ||
第四个参数,是这个trackbar上调节的范围(0~count) | ||
第五个参数,是调节trackbar时调佣的回调函数名 | ||
""" | ||
cv2.createTrackbar('min threshold','canny result',lowThreshold,max_lowThreshold,CannyThreshold) | ||
|
||
CannyThreshold(50) # 初始化 | ||
if cv2.waitKey(0) == 5: # wait for ESC key to exit cv2 | ||
cv2.destroyAllWindows() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# encoding = UTF-8 | ||
""" | ||
#!/usr/bin/env python 目的就是指出,你要用哪个python解释器去运行它 | ||
""" | ||
|
||
import cv2 | ||
import numpy as np | ||
from matplotlib import pyplot as plt | ||
|
||
img = cv2.imread("lenna.png",1) | ||
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) | ||
''' | ||
Sobel算子 | ||
Sobel算子函数原型如下: | ||
dst = cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) | ||
前四个是必须的参数: | ||
第一个参数是需要处理的图像; | ||
第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度; | ||
dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。 | ||
其后是可选的参数: | ||
dst是目标图像; | ||
ksize是Sobel算子的大小,必须为1、3、5、7。 | ||
scale是缩放导数的比例常数,默认情况下没有伸缩系数; | ||
delta是一个可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中; | ||
borderType是判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT。 | ||
''' | ||
|
||
img_sobel_x = cv2.Sobel(img_gray,cv2.CV_64F,1,0,ksize=3) # 对x求导 | ||
img_sobel_y = cv2.Sobel(img_gray,cv2.CV_64F,0,1,ksize=3) # 对y求导 | ||
|
||
# Laplace 算子 | ||
img_laplace = cv2.Laplacian(img_gray,cv2.CV_64F,ksize=3) | ||
|
||
# canny 算子 | ||
img_canny = cv2.Canny(img_gray,50,150) | ||
|
||
plt.subplot(231),plt.imshow(img_gray,"gray"),plt.title("正常") | ||
plt.subplot(232),plt.imshow(img_sobel_x,"gray"),plt.title("img_sobel_x") | ||
plt.subplot(233),plt.imshow(img_sobel_y,"gray"),plt.title("img_sobel_y") | ||
plt.subplot(234),plt.imshow(img_laplace,"gray"),plt.title("laplace") | ||
plt.subplot(235),plt.imshow(img_canny,"gray"),plt.title("img_canny") | ||
plt.show() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import cv2 | ||
import numpy as np | ||
|
||
img = cv2.imread("photo1.jpg") # 读图 | ||
result3 = img.copy() # 复制原图 | ||
|
||
""" | ||
注意这里src和dst的输入不是图像,而是图像对应的顶点坐标 | ||
""" | ||
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) | ||
|
||
# 生成透视变换矩阵warpMatrix,进行透视变换,参数1:原图上的点 参数2:目标图上的点 | ||
m = cv2.getPerspectiveTransform(src,dst) # 获取逆透视变换矩阵函数warpMatrix的各参数(a11~a33) | ||
print("warpMatrix:\n",m) | ||
|
||
""" | ||
warpPerspective函数,使指定的矩阵变化源图像. | ||
cv.warpPerspective (InputArray src, OutputArray dst, dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar &borderValue=Scalar()) | ||
参数说明如下: | ||
InputArray src:输入图像 | ||
OutputArray dst:输出大小为dsize | ||
dsize:目标图像的大小,以元组形式表示,例如(width, height) | ||
***以下为默认值*** | ||
flags: 插值方法的标志,用于指定插值方法,默认为cv2.INTER_LINEAR | ||
borderMode: 边界模式,用于指定超出边界的像素处理方式,默认为cv2.BORDER_CONSTANT | ||
borderValue: 当边界模式为cv2.BORDER_CONSTANT时,用于指定边界像素的值,默认为0。 | ||
""" | ||
result = cv2.warpPerspective(result3,m,(337,488)) | ||
cv2.imshow("src",img) | ||
cv2.imshow("result",result) | ||
cv2.waitKey(0) |