积分图&边缘检测
- 一、积分图
- 1.1 标准求和积分cv2.integral()
- 1.2 平方和求积分cv2.integral2()
- 1.3 倾斜求和积分cv2.integral3()
- 二、Canny边缘检测cv2. Canny()
一、积分图
积分图是一种允许子区域内像素快速求和的数据结构。 opencv支持积分图的三种变体分别为:求和、平方求和、倾斜求和。每种情况的结果在图像的每个方向上都加1之后,与原始图像的大小相同。通过积分图,可以对图像的任意直立或倾斜的矩形区域的像素进行求和、平局以及标准差。并且计算复杂度控制为O(1)
左:原图像灰度值。右:图像积分图
求原图被20包围的矩形区域,398-9-10+1
1.1 标准求和积分cv2.integral()
sum= cv2. integral(src, sum=None, sdepth=None)
参数 | 含义 |
src | 输入图像数组 |
sum | 输出图像数组,如果输入图像的大小为W×H则输出图像的大小为(W+1)×(H+1) |
sdepth | 指明求和图像(结果图像)需要的深度,可以是cv2.S32、cv2.F64 |
import cv2
import numpy as np
filename = r'D:\Project\Opencv\Learning03\image03.png'
image = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
cv2.imshow('origin', image)
h, w = image.shape[:2] # 把图片2像素的行数,列数以及通道数返回给rows,cols,channels
sum = np.zeros((h + 1, w + 1), dtype=np.float32) # 创建指定大小的数组,数组元素以 0 来填充:
imageIntegral = cv2.integral(image, cv2.CV_32FC1) # 计算积分图
result = np.zeros((h + 1, w + 1), dtype=np.uint8)
cv2.normalize(imageIntegral, result, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1) # 归一化处理
cv2.imshow("Image", result)
cv2.waitKey()
1.2 平方和求积分cv2.integral2()
sum,sdepth= cv2. integral2(src, sum=None, sqsum=None, sdepth=None, sqdepth=None)
参数 | 含义 |
src | 输入图像数组 |
sum | 标准求和,输出图像数组,如果输入图像的大小为W×H则输出图像的大小为(W+1)×(H+1) |
sqsum | 平方和,输出图像数组,如果输入图像的大小为W×H则输出图像的大小为(W+1)×(H+1) |
sdepth | 指明求和图像(结果图像)需要的深度,可以是cv2.S32、cv2.F64 |
1.3 倾斜求和积分cv2.integral3()
sum,sdepth,tilted= cv2. integral3(src, sum=None, sqsum=None, tilted=None, sdepth=None, sqdepth=None)
参数 | 含义 |
src | 输入图像数组 |
sum | 标准求和,输出图像数组,如果输入图像的大小为W×H则输出图像的大小为(W+1)×(H+1) |
sqsum | 平方和,输出图像数组,如果输入图像的大小为W×H则输出图像的大小为(W+1)×(H+1 |
tilted | 附加参数,得到附加结果 |
sdepth | 指明求和图像(结果图像)需要的深度,可以是cv2.S32、cv2.F64 |
二、Canny边缘检测cv2. Canny()
在canny算法中,现在x,y方向上求一阶导数,然后将他们组合成4个方向上的导数。
dst= cv2. Canny(image, threshold1, threshold2, apertureSize=None, L2gradient=None)
参数 | 含义 |
image | 输入图像数组 |
threshold1 | 低阈值 |
threshold2 | 高阈值 |
apertureSize=None | 算法调用sobel算子所用的aperture大小 |
edges=None | 附加参数,得到附加结果 |
L2gradient=None | 用于选择使用适当的L2范数‘正确’计算方向梯度,还是使用速度快但精度低的L1范数 |
canny算法使用了两个阈值,高阈值和低阈值,如果一个像素的梯度大于高阈值,就认定为边缘,如果一个像素的梯度小鱼低阈值则抛弃该像素(非边缘),如果一个像素的梯度介于低阈值和高阈值之间,只有当这个像素连接到一个高于高阈值的像素时,才认定为边缘,否者抛弃该像素(非边缘)。通常canny算法建议高低阈值比为2:1——3:1之间。
canny算法要求输入为单通道图像,输出图像是灰度图(实际上是一副布尔图)
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
'''canny边缘提取'''
def canny_demo(image):
# 1.高斯模糊:最后两个参数给定一个就可以自动求取另一个,所以只给其中一个赋值就可以
blur=cv.GaussianBlur(image,(3,3),0)
#2.灰度处理
gray=cv.cvtColor(blur,cv.COLOR_BGR2GRAY)
#3.求取梯度,也可以不用梯度,直接将灰度图传入cv.canny
grad_x=cv.Sobel(gray,cv.CV_16SC1,1,0)
grad_y = cv.Sobel(gray, cv.CV_16SC1, 0, 1)
#4.求边缘
edge_output=cv.Canny(grad_x,grad_y,50,150)#参数:x梯度,y梯度 ,低阈值,高阈值
cv.imshow('canny-demo',edge_output)
dst=cv.bitwise_and(image,image,mask=edge_output)
cv.imshow('color edge',dst)
img=cv.imread(r'D:\Project\Opencv\Learning01\fang.png')
cv.imshow('origin',img)
canny_demo(img)
cv.waitKey(0)