一幅二维图像可以由一个矩阵
或数组
表示,我们可以把它理解为一个二元函数 f ( x , y ) f(x,y) f(x,y),其中 x x x和 y y y是空间坐标, f f f表示该坐标处的值,也就是图像在该点的强度
或者灰度
。
常见的成像方式有:
名称 | 波长 | 性质 | 应用 |
---|---|---|---|
γ \gamma γ射线 | < 1 0 − 10 <10^{-10} <10−10 | 从原子核内发出来的,穿透能力强,对生物的破坏力大 | 大脑生理信号EGG |
χ \chi χ射线 | ( 10 − 0.01 ) × 1 0 − 9 (10-0.01)×10^{-9} (10−0.01)×10−9 | 不同部位对其吸收率不同 | CT |
紫外线 | ( 380 − 10 ) × 1 0 − 9 (380-10)×10^{-9} (380−10)×10−9 | 化学效应,荧光效应 | 生物医学领域 |
可见光 | ( 7.8 − 3.8 ) × 1 0 − 7 (7.8-3.8)×10^{-7} (7.8−3.8)×10−7 | 光线照在物体上,反射到人眼中 | |
红外线 | ( 1000 − 0.78 ) × 1 0 − 6 (1000-0.78)×10^{-6} (1000−0.78)×10−6 | 自然界一切物体都可以辐射红外线 | 红外图像;红外测温 |
微波 | 0.1 c m − 1 m 0.1cm-1m 0.1cm−1m | 辐射 | 雷达;通讯系统;微波影像 |
射频 | 0.1 c m − 3000 m 0.1cm-3000m 0.1cm−3000m | 电视;无线电广播;医学成像 |
图像格式
BMP
:未经压缩,文件较大;
JPEG
:有损压缩,互联网上广泛使用;
GIF
:可以是动画,支持透明背景,但色域不太广;
PNG
:压缩比高于GIF,支持透明图像,可通过Alpha通道调节透明度;
TIFF
:图像格式复杂,存储信息丰富,用于印刷;
图像的尺寸以像素为单位,灰度像素值范围在0~255之间,0代表黑色,255代表白色。
图像分辨率:单位长度中所具有的像素数量。
通道数:图像的位深度,图像中每个像素值所占的二进制数。越大可以表示的颜色越多,色彩越丰富逼真。
八位:单通道,灰度图,灰度值范围为0~255;
24位:三通道RGB,3*8=24;
32位:四通道:RGB+透明度Alpha通道;
颜色空间:RGB、HSV(色调;饱和度;明度)、HSI(色调;饱和度;强度)、CMYK(青;品;黄;黑)
灰度转换:将三通道转化为单通道图像cvt.cvtColor()
g r a y = B × 0.114 + G × 0.587 + R ∗ 0.299 gray = B×0.114+G×0.587+R*0.299 gray=B×0.114+G×0.587+R∗0.299
BGR转换为RGB:用cv读取图像时是按照BGR顺序存储的,若用plot画图需要将BGR转换为RGB。
通道分离:将彩色图像分离成B、G、R三个单通道图像cv2.split()
通道合并:对B、G、R三个单通道进行修改,最后将修改后的单通道合并成彩色图像cv2.merge()
直方图:直方图描述了图像中每个亮度值的像素数,左侧为纯黑、较暗;右侧为较亮、纯白。cv2.calcHist()
图像平移:
图像缩放:下采样,上采样。
插值方法:最近邻插值;双线性插值;
图像旋转:
仿射变换:
透视变换:
邻域算子:给定像素周围像素值决定给定像素的最终输入的一种算子。线性滤波是一种常用的邻域算子,其像素输出值取决于输入像素的加权和。
g ( i , j ) = ∑ k , l f ( i + k , j + l ) h ( k , l ) g(i,j)=\sum_{k,l}f(i+k,j+l)h(k,l) g(i,j)=k,l∑f(i+k,j+l)h(k,l)
线性滤波—方框滤波:
线性滤波—均值滤波:
线性滤波—高斯滤波:
非线性滤波—中值滤波:
非线性滤波—双边滤波:
直方图均衡化
Gamma变化:
图像腐蚀:
图像膨胀:
开运算:先腐蚀后膨胀把细微连在一起的两块目标分开。
闭运算:先膨胀再腐蚀,把细微连在一块的图封闭在一块。
形态学梯度:
顶帽和黑帽:
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
def best_thresh(img):
img_array = np.array(img).astype(np.float32)#转化成数组
I=img_array
zmax=np.max(I)
zmin=np.min(I)
tk=(zmax+zmin)/2#设置初始阈值
print(tk)
#根据阈值将图像进行分割为前景和背景,分别求出两者的平均灰度zo和zb
b=1
m,n=I.shape
while b==1:
ifg=0
ibg=0
fnum=0
bnum=0
# 遍历图像上每一点
for i in range(1,m):
for j in range(1,n):
tmp=I[i,j]
if tmp>=tk:
ifg=ifg+1
fnum=fnum+int(tmp)#前景像素的个数以及像素值的总和
else:
ibg=ibg+1
bnum=bnum+int(tmp)#背景像素的个数以及像素值的总和
#计算前景和背景的平均值
zo=int(fnum/ifg)
zb=int(bnum/ibg)
if tk==int((zo+zb)/2):#若前景和背景的平均值等于当前阈值,退出循环
b=0
else:
tk=int((zo+zb)/2)#否者更新阈值
return tk
img = cv2.imread("./image/bird.png")
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
img = cv2.resize(gray,(200,200))#大小
yvzhi=best_thresh(img)
ret1, th1 = cv2.threshold(img, yvzhi, 255, cv2.THRESH_BINARY)
print(ret1)
plt.imshow(th1,cmap=cm.gray)
plt.show()
结果:
otsu大津法:是一种基于全局阈值的自适应方法,使的分割结果有最大类间方差。
图像梯度:
模板卷积:
梯度算子:是一阶导数算子
Canny边缘检测算法:先平滑后求导的方法
边缘检测性能评价指标:
区域生长算法:
区域生长好坏的决定因素有:初始点(种子点)的选取、生长准则、终止条件。
代码实现:
区域生长代码
分水岭算法:给每个孤立的山谷(局部最小值)不同颜色的水(标签),当水涨起来,根据周围的山峰(梯度),不同的山谷也就是不同的颜色会开始合并,要避免山谷合并,需要在水要合并的地方建立分水岭,直到所有山峰都被淹没,所创建的分水岭就是分割边界线,这就是分水岭的原理。
# import cv2
"""
完成分水岭算法步骤:
1、加载原始图像
2、阈值分割,将图像分割为黑白两个部分
3、对图像进行开运算,即先腐蚀在膨胀
4、对开运算的结果再进行 膨胀,得到大部分是背景的区域
5、通过距离变换 Distance Transform 获取前景区域
6、背景区域sure_bg 和前景区域sure_fg相减,得到即有前景又有背景的重合区域
7、连通区域处理
8、最后使用分水岭算法
"""
import cv2
import numpy as np
# Step1. 加载图像
img = cv2.imread('image/yezi.jpg')
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Step2.阈值分割,将图像分为黑白两部分
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# cv2.imshow("thresh", thresh)
# Step3. 对图像进行“开运算”,先腐蚀再膨胀
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# cv2.imshow("opening", opening)
# Step4. 对“开运算”的结果进行膨胀,得到大部分都是背景的区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)
cv2.imshow("sure_bg", sure_bg)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Step5.通过distanceTransform获取前景区域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) # DIST_L1 DIST_C只能 对应掩膜为3 DIST_L2 可以为3或者5
cv2.imshow("dist_transform", dist_transform)
cv2.waitKey(0)
cv2.destroyAllWindows()
print(dist_transform.max())
ret, sure_fg = cv2.threshold(dist_transform, 0.1 * dist_transform.max(), 255, 0)
# Step6. sure_bg与sure_fg相减,得到既有前景又有背景的重合区域 #此区域和轮廓区域的关系未知
sure_fg = np.uint8(sure_fg)
unknow = cv2.subtract(sure_bg, sure_fg)
cv2.imshow("unknow", unknow)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Step7. 连通区域处理
ret, markers = cv2.connectedComponents(sure_fg,connectivity=8) #对连通区域进行标号 序号为 0 - N-1
#print(markers)
print(ret)
markers = markers + 1 #OpenCV 分水岭算法对物体做的标注必须都 大于1 ,背景为标号 为0 因此对所有markers 加1 变成了 1 - N
#去掉属于背景区域的部分(即让其变为0,成为背景)
# 此语句的Python语法 类似于if ,“unknow==255” 返回的是图像矩阵的真值表。
markers[unknow==255] = 0
# Step8.分水岭算法
markers = cv2.watershed(img, markers) #分水岭算法后,所有轮廓的像素点被标注为 -1
#print(markers)
img[markers == -1] = [0, 0, 255] # 标注为-1 的像素点标 红
cv2.imshow("dst", img)
cv2.waitKey(0)
cv2.destroyAllWindows()