- 全局阈值分割
- “cv.THRESH_TRIANGLE” 只有单个波峰时效果较好,分割细胞图
- 一般用"cv.THRESH_OTSU"
- “cv.THRESH_TRUNC”,截断,大于阈值设为阈值
- “THRESH_TOZERO”,小于阈值设为0
cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)#自动寻找阈值,"cv.THRESH_OTSU" 选取阈值的方法
- 局部阈值分割
- 适合光线不均匀的情况下
# binary=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,35,10)
# "35"块大小:必须为奇数,“10”:常数,像素-均值<10为0,大于10为255
binary=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,35,10)
# 高斯效果更好
import cv2 as cv
import numpy as np
def threshold_demo(image):#全局阈值分割
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
thr,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)#自动寻找阈值,"cv.THRESH_OTSU" 选取阈值的方法
# thr,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_TRIANGLE)#自动寻找阈值,"cv.THRESH_TRIANGLE" 只有单个波峰时效果较好,分割细胞图
# thr, binary = cv.threshold(gray, 100, 255, cv.THRESH_BINARY_INV ) # 设置寻找阈值范围,"cv.THRESH_BINARY_INV",取反
# thr, binary = cv.threshold(gray, 120, 255, cv.THRESH_TRUNC ) # \"cv.THRESH_TRUNC",截断,大于阈值设为阈值
# thr, binary = cv.threshold(gray, 120, 255, cv.THRESH_TOZERO ) # "THRESH_TOZERO",小于阈值设为0
print("threshold value %s"%thr)
# cv.imshow("gray",gray)
cv.imshow("threshold_demo_binary",binary)
# cv.imwrite('C:\Users\22852\Desktop\opencv\result\binary.jpg', binary)
def local_demo(image):#适合光线不均匀的情况下
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# binary=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,35,10)
# "35"块大小:必须为奇数,“10”:常数,像素-均值<10为0,大于10为255
binary=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,35,10)
# 高斯效果更好
# cv.imshow("gray",gray)
cv.imshow("local_demo_binary",binary)
# cv.imwrite('C:\Users\22852\Desktop\opencv\result\gauss_loc_binary.jpg',binary)
def costom_demo(image):#自己求均值的情况下
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
h,w=gray.shape[:2]
m=np.reshape(gray,[1,w*h])
mean=np.mean(m)
thr, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY_INV)
# 高斯效果更好
# cv.imshow("gray",gray)
cv.imshow("costom_demo_binary",binary)
src=cv.imread('C:\Users\22852\Desktop\opencv\data\girl.jpg')
# cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image:",src)
costom_demo(src)
local_demo(src)
threshold_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
2. 超大图像二值化
def big_demo(image):
cw=512#每个小块的高和宽,相当于kerne
ch=512
h,w=image.shape[:2]
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
for row in range(0,h,ch):
for col in range(0,w,cw):
roi=gray[row:row+ch,col:col+cw]
# thr,dst=cv.threshold(roi,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)#全局
dst=cv.adaptiveThreshold(roi,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,127,15)#局部
#对每个分块进行二值化
# if(np.std(dst)<60):#std=0为空白图像
# dst=0
gray[row:row + ch, col:col + cw] = dst
print("std",np.std(dst),"mean",np.mean(dst))
cv.imwrite('C:\Users\22852\Desktop\opencv\result\big_local_binary.jpeg',gray)
原图
全局二值化结果
局部二值化结果
- sobel\Scharr算子:对像素求一阶导,在其一阶导数在边缘位置为极值,极值处就是边缘,Scharr:sobel算子的增强版本。
- 分别求x、y方向得梯度
- 进行归一化
- 求加权梯度
def sobel_demo(image):#sobel\Scharr算子,对像素求一阶导
grad_x=cv.Sobel(image,cv.CV_32F,1,0)
grad_y=cv.Sobel(image,cv.CV_32F,0,1)
# grad_x=cv.Scharr(image,cv.CV_32F,1,0)
# grad_y=cv.Scharr(image,cv.CV_32F,0,1)#sobel算子的增强版本
gradx=cv.convertScaleAbs(grad_x)#Scales, calculates absolute values, and converts the result to 8-bit.
grady=cv.convertScaleAbs(grad_y)
cv.imshow("graid_x",gradx)
cv.imshow("graid_y",grady)
grad=cv.addWeighted(gradx,0.5,grady,0.5,0)#Calculates the weighted sum of two arrays.dst = src1*alpha + src2*beta + gamma;
cv.imshow("grandient",grad)
def Scharr_demo(image):#sobel\Scharr算子,对像素求一阶导
grad_x=cv.Scharr(image,cv.CV_32F,1,0)
grad_y=cv.Scharr(image,cv.CV_32F,0,1)#sobel算子的增强版本
gradx=cv.convertScaleAbs(grad_x)#Scales, calculates absolute values, and converts the result to 8-bit.
grady=cv.convertScaleAbs(grad_y)
cv.imshow("graid_x",gradx)
cv.imshow("graid_y",grady)
grad=cv.addWeighted(gradx,0.5,grady,0.5,0)#Calculates the weighted sum of two arrays.dst = src1*alpha + src2*beta + gamma;
cv.imshow("grandient",grad)
sobel
Scharr
- Laplacian算子:对像素值求二阶导数,会发现边缘处的导数值为0
- 直接设置kernelsize大小(也可以自己定义kernel的值)
- 进行加权
def laplian_demo(image):#拉普拉斯算子:对像素值求二阶导数,会发现边缘处的导数值为0
# dst=cv.Laplacian(image,cv.CV_32F,ksize=3)#ksize默认3
# lpls=cv.convertScaleAbs(dst)
kernel=np.array([[1,1,1],
[1,-8,1],
[1,1,1]])
dst=cv.filter2D(image,cv.CV_32F,kernel=kernel)
lpls = cv.convertScaleAbs(dst)
cv.imshow("laplian",lpls)
原理
4. 图像金字塔- 图像金字塔: 高斯金字塔、拉普拉斯金字塔(w、h必须相同)
- 以多分辨率来解释图像的一种有效但概念简单的结构就是图像金字塔。
- 一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低的图像集合。
- 金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。
- 个人理解:
- resize、上采样、下采样改变的改变的时图像尺度;
- 图像尺度是指长宽多少个像素,分辨率是指单位面积里的像素个数
def pyramid_demo(image):#高斯金字塔
temp=image.copy()
pyramid_image=[]
level=3
for i in range(level):
dst=cv.pyrDown(temp)#reduce= 模糊+下采样
pyramid_image.append(dst)
cv.imshow("pyramid_down"+str(i),dst)
temp=dst.copy()
return pyramid_image
def lapalian_demo(image):#拉普拉斯金字塔
pyramid_images=pyramid_demo(image)
level=len(pyramid_images)
for i in range(level-1,-1,-1):
if(i-1)<0:
expands = cv.pyrUp(pyramid_images[i], dstsize=image.shape[:2]) # 图像上采样
lpls=cv.subtract(image,expands)#相减
cv.imshow("lapalian_demo_" + str(i), lpls)
else:
expands = cv.pyrUp(pyramid_images[i], dstsize=pyramid_images[i - 1].shape[:2]) # 图像上采样,wh必须相等
lpls=cv.subtract(pyramid_images[i-1],expands)#相减
cv.imshow("lapalian_demo_" + str(i), lpls)
5. Candy边缘提取
- Candy算法介绍:
- 高斯模糊——GaussianBlur,降低噪声,candy对噪声敏感
- 灰度转换——cvtColor,
- 梯度计算——Soble/Scharr,
- 非最大信号抑制,
- 高低阈值连接输出二值图像
def edge_demo(image):
blurred=cv.GaussianBlur(image,(3,3),0)#sigmaX Gaussian kernel standard deviation in X direction.
gray=cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)
xgrad=cv.Sobel(gray,cv.CV_16SC1,1,0)
ygrad=cv.Sobel(gray,cv.CV_16SC1,0,1)
dst=cv.Canny(xgrad,ygrad,50,150)
# dst=cv.Canny(image,50,150)
# dst=cv.Canny(blurred,50,150)
cv.imshow("Candy Edge:",dst)
color_edge=cv.bitwise_and(image,image,mask=dst)
cv.imshow("Color Edge",color_edge)
其实直接对原图进行边缘提取也是一样的
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)