0%

图像处理总结

图像处理总结

持续更新ing~~

欢迎各位老师和同学提出更好的建议,直接评论即可

先贴一张从csdn上看到的CV技能树,我的想法是:CV方向可以试试,挺有趣

img

一.图像处理基础

图像

图像是由像素(pixel)组成的,像素是图像最小单位,是“小方格”,这些像素决定了图像在屏幕上的清晰度。

图像在计算机中的表达形式是矩阵

图像通常包括:二值图像,灰度图像,彩色图像

二值图像:

非黑(像素0)即白(像素255)

灰度图像:

黑白灰,灰度划分为256种不同的颜色,将彩色图像转换为灰度图是图像处理的最基本预处理操作。

彩色图像:

BGR图像(不同的器件可能不一样,人们习以为常说成RGB,而opencv中是RGB,甚至康佬曾说有一个器件是GBR),R红G绿B蓝这三原色按照不同的比例,作为三色通道,组成计算机所有的原色。

ROI区域

region of interest

是从图像中勾勒出需要处理的区域,广泛用于热点地图、人脸识别、图像分割等领域。

导包

1
2
3
import cv2
import numpy as np
import matplotlib.pyplot as plt

opencv常用函数

安装过程请自行百度

读入图像

1
2
3
4
5
6
img = cv2.imread("文件名",参数)
#常用参数:(参数也可以没有)
#IMREAD_UNCHANGED(图像不变)
#IMREAD_GRAYSCALE(灰度图像)
#IMREAD_COLOR(彩色图像)
#COLOR_BGR2RGB(BGR转RGB)

显示图像

1
cv2.imshow(窗口名,图像名)

窗口等待

1
2
3
4
5
cv2.waitKey(delay)
#delay:表示等待毫秒数,将等待特定的几毫秒,看键盘是否有输入,返回值为ASCII值。
#参数为0,则表示无限期的等待键盘输入;
#参数>0表示等待delay毫秒;
#参数<0表示等待键盘单击。

删除窗口

1
2
cv2.destroyAllWindows()
#删除所有窗口

写入图片

1
cv2.imwrite(文件地址,文件名)

读取像素

1
2
3
4
5
6
#灰度图像
a = img[12,45]
#彩色图像
b = img[12,45,0]
g = img[12,45,1]
r = img[12,45,2]

修改图像

1
2
3
#单个像素直接赋值即可
#区域像素
img[20:100,30:80] = [255,255,255]

形状、像素数目、类型

1
2
3
4
5
6
img.shape()
#返回行数、列数、通道数
img.size()
#像素数量
img.dtype()
#图像类型,通常为uint8

通道拆分与合并

1
2
3
4
5
6
7
8
9
b = img[:,:,0]
g = img[:,:,1]
r = img[:,:,2]
#或者使用split()函数
b,g,r = cv2.split()
#获取不同通道
b = cv2.split(img)[0]
#合并:merge()
res = cv2.merge([b,g,r])

numpy常用函数

读取像素

1
2
3
b = img.item(12,45,0)
g = img.item(12,45,1)
r = img.item(12,45,2)

修改像素

1
2
#itemset(位置,新像素值)
b = img.item((12,45),243)

后续有常用的会继续添加

Matplotlib.pyplot常用函数

1
2
3
4
plt.subplot(2,2,1)#example
#两行两列,编号为1
plt.xticks()#设置x轴
plt.yticks()#设置y轴

二.图像基本操作

(一)图像加法运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#Numpy库:运算结果取模运算
1.值>255:结果对255取模
2.值<=255:图像1+图像2
#openCV库
1.值>255:结果为255
2.值<=255:图像1+图像2
#eg code
#读取图片
img = cv2.imread("pic.jpg")
test = img

#方法一:Numpy加法运算
result1 = img + test

#方法二:OpenCV加法运算
result2 = cv2.add(img, test)

#显示图像
cv2.imshow("org", img)
cv2.imshow("res1", result1)
cv2.imshow("res2", result2)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

参与运算的图像大小和类型必须一致

(二)图像融合

1
2
3
res = cv2.addWeighter(org,alpha,ano,beta,gamma)
#res = org*alpha + ano*beta + gamma
#gamma:亮度调节值,不能省略

两张融合的图像像素大小需要一致

(三)图像类型转换

图像处理通常需要将彩色图像转换为灰度图像再进行后续的操作

1
2
3
4
#最常见的包括3类
cv2.COLOR_BGR2GRAY
cv2.COLOR_BGR2RGB
cv2.COLOR_GRAY2BGR

(四)图像阈值化处理

1.通用函数

1
2
3
4
5
6
7
8
#函数threshold
retval , dst = cv2.threshold(src,thresh,maxval,type)
#retval阈值
#dst处理结果
#src源图像
#threshold阈值
#maxval最大值
#type类型

2.阈值化

二值化或阈值化(Binarization)旨在提取图像中的目标物体,将背景以及噪声区分开来。通常会设定一个阈值T,通过T将图像的像素划分为两类:大于T的像素群和小于T的像素群。

二进制阈值化(cv2.THRESH_BINARY)

灰度值大于阈值:设其灰度值为max

灰度值小于阈值:0

反二进制阈值化(cv2.THRESH_BINARY_INV)

灰度值大于阈值:0

灰度值小于阈值:设其灰度值为255

截断阈值化(cv2.THRESH_TRUNC)

灰度值大于阈值:设为该阈值

灰度值小于阈值:不变

阈值化为0(cv2.THRESH_TOZERO)

灰度值大于阈值:0

灰度值小于阈值:不变

反阈值化为0(cv2.THRESH_TOZERO_INV)

灰度值大于阈值:不变

灰度值小于阈值:0

3.代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import cv2
import numpy as np
import matplotlib.pyplot as plt
src = cv2.imread("test1.jpg")
#灰度图像处理
grayImg = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
#二进制阈值化
r , a = cv2.threshold(grayImg,127,255,cv2.THRESH_BINARY)
#反二进制阈值化
r , b = cv2.threshold(grayImg,127,255,cv2.THRESH_BINARY_INV)
#截断阈值化
r , c = cv2.threshold(grayImg,127,255,cv2.THRESH_TRUNC)
#阈值化为0
r , d = cv2.threshold(grayImg,127,255,cv2.THRESH_TOZERO)
#反阈值化为0
r , e = cv2.threshold(grayImg,127,255,cv2.THRESH_TOZERO_INV)

#显示多个图像
titles = ['GrayImg','Binary','Binary_inv','Trunc','Tozero','Tozero_inv']
images = [grayImg,a,b,c,d,e]
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()

4.运行结果

img

(五)图像腐蚀与膨胀

是两种基本的形态学运算,主要用于图像中的极大区域和极小区域,包含两个输入对象:

二值图像、卷积核

形态学:主要针对二值图像

1.图像膨胀dilation(领域扩张)

运算符号:

定义:

该公式表示用B来对图像A进行膨胀处理,其中B是一个卷积模板或卷积核,其形状可以为正方形或圆形,通过模板B与图像A进行卷积计算,扫描图像中的每一个像素点,用模板元素与二值图像元素做“与”运算,如果都为0,那么目标像素点为0,否则为1。从而计算B覆盖区域的像素点最大值,并用该值替换参考点的像素值实现膨胀。

2.图像腐蚀erosion(领域蚕食)

运算符号:

定义:

该公式表示图像A用卷积模板B来进行腐蚀处理,通过模板B与图像A进行卷积计算,得出B覆盖区域的像素点最小值,并用这个最小值来替代参考点的像素值。

3.代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import cv2
from matplotlib import image
import numpy as np
import matplotlib.pyplot as plt
#二值化
src = cv2.imread("test1.jpg",cv2.IMREAD_UNCHANGED)
#设置卷积核
kernel = np.ones((5,5),np.uint8)

#膨胀处理
erosion = cv2.erode(src,kernel)
#腐蚀处理
dilate = cv2.dilate(src,kernel)
titles = ['source','erosion','dilate']
images = [src,erosion,dilate]
for i in range(3):
plt.subplot(1,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()

cv2.waitKey(0)
cv2.destroyAllWindows()

4.运行结果

img

(六)图像开闭梯度运算

1.概念

图像被腐蚀后,去除了噪声,但是也压缩了图像;接着对腐蚀过的图像进行膨胀处理,可以去除噪声,并保留原有图像。

有助于关闭前景物体内部的小孔,或物体上的小黑点。

膨胀图像减去腐蚀图像的结果,得到图像的轮廓,其中二值图像1表示白色点,0表示黑色点。

2.通用函数

3.代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("test1.jpg")
kernel = np.ones((5,5),np.uint8)
res1 = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
res2 = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
res3 = cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
titles = ["source","open","close","grad"]
images = [img,res1,res2,res3]
for i in range(4):
plt.subplot(1,4,i+1),plt.imshow(images[i])
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()

4.运行结果

img

(七)顶帽黑帽运算

1.概念

2.通用函数

3.代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import cv2
import numpy as np
import matplotlib.pyplot as plt

src = cv2.imread("test1.jpg")
kernel = np.ones((10,8),np.uint8)
#kernel里面值越大,获取细节越多
res1 = cv2.morphologyEx(src,cv2.MORPH_TOPHAT,kernel)
res2 = cv2.morphologyEx(src,cv2.MORPH_BLACKHAT,kernel)
titles = ["src","tophat","blackhat"]
images = [src,res1,res2]
for i in range(3):
plt.subplot(1,3,i+1),plt.imshow(images[i])
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()

4.运行结果

img

(八)灰度直方图(histogram)

1.概念

灰度直方图是灰度级的函数,描述的是图像中每种灰度级像素的个数,反映了每种灰度出现的频率。

横坐标:灰度级

纵坐标:灰度级出现的频率

对于连续图像,平滑地从中心的高灰度级变化到边缘的低灰度级。

2.matplotlib绘制直方图

1
2
3
4
#导包
import matplotlib.pyplot as plt
#函数
hist(数据源,像素级)

数据源必须是一维数组,通常要ravel()函数来拉直图像

1
2
b = a.ravel()
#将多维数组降为一维数组

像素级一般是256,表示[0,255]

代码实现

1
2
3
4
5
6
7
import cv2
import numpy as np
import matplotlib.pyplot as plt

src = cv2.imread("test1.jpg")
plt.hist(src.ravel(),256)
plt.show()

结果

img

(九)图像几何变换总结

关于plt画图出现和源文件不一致问题的修正:

1
2
3
#添加代码:
src = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#后面就用这里的src来进行处理

新知识:仿射变换、透视变换

1.仿射变换

为输出图像坐标,为输入图像坐标,仿射变换可以表示为:

对应矩阵为:

其中T有如下形式:

img

仿射变换函数接口:

1
2
3
4
5
6
7
8
9
warpAffine(
InputArray src, 输入图像
OutputArray dst, 输出图像
InputArray M, 仿射计算矩阵
Size dsize, 输出图像大小
int flags = INIET_LINEAR, 插值方法
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar()
);

2.拓展:线性变换

设算子,对线性空间上的任意元素,以及数域中任意,都有:

可以合并为:

对于仿射变换来讲:

对坐标进行线性变换:

则有:

【注】上面的过程证明了神经网络需要激活函数的原因

因为权重计算过程的本质就是矩阵的计算,而单纯的矩阵计算一定是线性变换,多层网络模型只是多个线性变换的叠加,其实可以表示为一个变换,如下:

所以神经网络为了拟合更加复杂的函数,必须添加非线性变换,即激活函数

只要是矩阵变换,就一定是线性变换

不过对于神经网络来说,传统表示会用添加1来进行维度对齐,则对于内存的利用率太低,故一般形式改为:

对应到图像处理中就是如下形式:

3.透视变换

透视变换(perspective transformation)是将物体重新投影到一个新的视角或成像平面,常用于机器人视觉导航研究中,由于相机视场与地面存在倾斜角使得物体成像产生畸变,通常使用透视变换实现对物体图像的校正。

透视变换作用域是三维坐标系,变换矩阵是一个3x3的矩阵。从另一个角度来说,仿射变换也可以看作是一种特殊的透视变换。

两条平行线仿射变换后仍然保持平行,但透视变换不保证这一点。

透视变换函数接口:

1
2
3
4
5
6
7
8
9
void warpPerspective(
InputArray src, 源图像
OutputArray dst, 输出图像
InputArray M, 透视变换矩阵M:3x3
Size dsize, 输出图像尺寸
int flags=INTER_LINEAR, 插值方法标志
int borderMode=BORDER_CONSTANT, 像素边界外推方法标志
const Scalar& borderValue=Scalar() 填充边界使用的数值,默认为0
);

4.整体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("test1.jpg")
image = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#图像平移矩阵
M = np.float32([[1,0,80],[0,1,30]])
rows , cols = image.shape[:2]
img1 = cv2.warpAffine(image,M,(cols,rows))

#图像缩小
img2 = cv2.resize(image,(200,100))
#图像放大
img3 = cv2.resize(image,None,fx=1.2,fy=1.2)

#绕图像的中心旋转
#源图像的高、宽以及通道数
rows, cols, channel = image.shape

#函数参数:旋转中心 旋转度数 scale
M = cv2.getRotationMatrix2D((cols/2, rows/2), 30, 1)

#函数参数:原始图像 旋转参数 元素图像宽高
img4 = cv2.warpAffine(image, M, (cols, rows))

#图像翻转
img5 = cv2.flip(image, 0) #参数=0以X轴为对称轴翻转
img6 = cv2.flip(image, 1) #参数>0以Y轴为对称轴翻转

#图像的仿射
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1,pts2)
img7 = cv2.warpAffine(image, M, (rows,cols))

#图像的透射
pts1 = np.float32([[56,65],[238,52],[28,237],[239,240]])
pts2 = np.float32([[0,0],[200,0],[0,200],[200,200]])
M = cv2.getPerspectiveTransform(pts1,pts2)
img8 = cv2.warpPerspective(image,M,(200,200))
#循环显示图形
titles = [ 'source', 'shift', 'reduction', 'enlarge', 'rotation', 'flipX', 'flipY', 'affine', 'transmission']
images = [image, img1, img2, img3, img4, img5, img6, img7, img8]
for i in range(9):
plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()

5.运行结果

img

(十)图像灰度化处理

图像处理过程中,常常需要用到灰度图像、二值图像、HSV、HSI等颜色,OpenCV提供了cvtColor()函数实现这些功能。

1
2
3
4
5
dst = cv2.cvtColor(src,code,[,dst[,dstCn])
dst :输出图像,大小和深度与src一致
src :输入图像,需要进行颜色空间变换的原图像
code:转换的代码或标识
dstCn:目标图像通道数。值为0时,则由src和code决定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import cv2  
import numpy as np
import matplotlib.pyplot as plt

#读取原始图像
img_BGR = cv2.imread("test1.jpg")

#BGR转换为RGB
img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)

#灰度化处理
img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY)

#BGR转HSV
img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV)

#BGR转YCrCb
img_YCrCb = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb)

#BGR转HLS
img_HLS = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HLS)

#BGR转XYZ
img_XYZ = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2XYZ)

#BGR转LAB
img_LAB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2LAB)

#BGR转YUV
img_YUV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YUV)

#调用matplotlib显示处理结果
titles = ['BGR', 'RGB', 'GRAY', 'HSV', 'YCrCb', 'HLS', 'XYZ', 'LAB', 'YUV']
images = [img_BGR, img_RGB, img_GRAY, img_HSV, img_YCrCb,
img_HLS, img_XYZ, img_LAB, img_YUV]
for i in range(9):
plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()

运行结果

img

(十一)图像傅里叶变换

基础知识去看信号与系统,直接上代码,不多bb

傅里叶变换主要是将时间域上的信号转变为频率域上的信号,用来进行图像降噪、图像增强等处理。

高频信号往往是图像中的边缘信号和噪声信号,而低频信号包含图像变化频繁的图像轮廓以及背景信号。

结果图像中,中心的图像表示低频信号,边缘的图像代表高频图像,需要注意的是,原图像和傅里叶变换结果的图像不是一一对应的。

快速傅里叶变换(FFT)

快速傅里叶变换是傅里叶变换的快速算法而已,主要是能减少运算量和存储开销,对于硬件实现特别有利。

作用:大大降低了运算量,使得让计算机处理信号成为可能。

Numpy实现傅里叶变换、逆变换

FFT包提供函数np.fft.fft2()对信号进行快速傅里叶变换

函数原型:

1
2
3
4
5
6
7
ff2(a,s=None,axes=(-2,-1),norm=None)
#a表示图像
#s表示整数序列,决定输出数组的大小
#axes表示整数序列,用于计算FFT可选轴
#norm包含None和ortho两个选项,默认值为None
ifft2(a,n=None,axis=-1,norm=None)
#实现逆变换,返回复数数组

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# coding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

#必须先转化成灰度图像,否则无法显示
src = cv2.imread("lena.jpg",cv2.IMREAD_GRAYSCALE)
#傅里叶变换
f = np.fft.fft2(src)
#将频谱图像的中心低频部分移动至左上角
fshift = np.fft.fftshift(f)
#将复数转换为0至255范围并用对数表示
res = np.log(np.abs(fshift))

#傅里叶逆变换
ishift = np.fft.ifftshift(fshift)
img = np.fft.ifft2(ishift)
img = np.abs(img)#一定要转换成绝对值,否则float处理会报错

titles = ["src","fft","ifft"]
images = [src,res,img]
for i in range (3):#range函数 在0-2闭区间生成整数
plt.subplot(1,3,i+1)
plt.imshow(images[i],'gray')#以灰度图的方式才能显示
plt.title(titles[i])
plt.xticks(),plt.yticks()
plt.axis('off')#显示横纵坐标
plt.show()

运行结果

img

Opencv实现傅里叶变换、逆变换

opencv实现结果和numpy是一样的,但是opencv的是双通道的。通道1是结果实数部分,通道2是结果虚数部分,且输入图像要转换成np.float32形式。

1
2
3
4
5
dst = cv2.dft(src,dst=None,flags = None,nonzeroRows=None)
#src 输入图像 转换成np.float32形式
#dst 输出图像 包含输出大小和尺寸
#flags 转换标记
#nonzeroRows 表示当参数不为零时,函数假定只有nonzeroRows输入数组的第一行(未设置)或者只有输出数组的第一个(设置)包含非零

注意,由于输出的频谱结果是一个复数,需要调用cv2.magnitude()函数将傅里叶变换的双通道结果转换为0到255的范围。

1
2
3
4
5
6
7
8
cv2.magnitude(x,y)
#x:实部
#y:虚部
cv2.idft(src[, dst[, flags[, nonzeroRows]]])
#src表示输入图像,包括实数或复数
#dst表示输出图像
#flags表示转换标记
#nonzeroRows表示要处理的dst行数

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import numpy as np
import cv2
from matplotlib import pyplot as plt

#读取图像
img = cv2.imread("lena.jpg", 0)

#傅里叶变换
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)
dftshift = np.fft.fftshift(dft)
res1= 20*np.log(cv2.magnitude(dftshift[:,:,0], dftshift[:,:,1]))

#傅里叶逆变换
ishift = np.fft.ifftshift(dftshift)
iimg = cv2.idft(ishift)
res2 = cv2.magnitude(iimg[:,:,0], iimg[:,:,1])

titles = ["src","Fourier","Inverse Fourier"]
images = [img,res1,res2]
for i in range (3):#range函数 在0-2闭区间生成整数
plt.subplot(1,3,i+1)
plt.imshow(images[i],'gray')#以灰度图的方式才能显示
plt.title(titles[i])
plt.xticks(),plt.yticks()
plt.axis('off')#显示横纵坐标
plt.show()

运行结果

img

(十二)图像量化、采样(project关键)

量化

自然界图像是模拟信号,只有将连续的信号离散化,图像转换为数字图像,才能进行下一步处理。

量化等级越多,图像层次越丰富,灰度分辨率越高,图像的质量也越好;量化等级越少,图像层次欠丰富,灰度分辨率越低,会出现图像轮廓分层的现象,降低了图像的质量。

1.操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import cv2
import numpy as np
import matplotlib.pyplot as plt
src = cv2.imread("lena.jpg",cv2.IMREAD_UNCHANGED)
height = src.shape[0]
width = src.shape[1]
new_img = np.zeros((height,width,3),np.uint8)

for i in range(height):
for j in range(width):
for k in range(3):#对应RGB3个分量
if src[i, j][k] < 32:
gray = 0
elif src[i, j][k] < 64:
gray = 32
elif src[i, j][k] < 96:
gray = 64
elif src[i, j][k] < 128:
gray = 96
elif src[i, j][k] < 160:
gray = 128
elif src[i, j][k] < 192:
gray = 160
elif src[i, j][k] < 224:
gray = 192
else:
gray = 224
new_img[i, j][k] = np.uint8(gray)

titles = ["src","process"]
images = [src,new_img]
for i in range(2):
plt.subplot(1,2,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])

plt.show()

2.运行结果

img

3.K-Means聚类量化处理(拓展)

聚类是在事先并不知道任何样本标签的情况下,通过数据之间的内在关系把样本划分为若干类别,使得同类别样本之间的相似度高,不同类别之间的样本相似度低。

KMenas的优点:

  • 高效可伸缩,计算复杂度为接近于线性(N是数据量,K是聚类总数,t是迭代轮数)。
  • 收敛速度快,原理相对通俗易懂,可解释性强。

KMeans也有一些明显的缺点:

  • 受初始值和异常点影响,聚类结果可能不是全局最优而是局部最优。
  • K是超参数,一般需要按经验选择
  • 样本点只能划分到单一的类中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# coding: utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

#读取原始图像
img = cv2.imread("test1.jpg")

#图像二维像素转换为一维
data = img.reshape((-1,3))
data = np.float32(data)

#定义中心 (type,max_iter,epsilon)
criteria = (cv2.TERM_CRITERIA_EPS +
cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)

#设置标签
flags = cv2.KMEANS_RANDOM_CENTERS

#K-Means聚类 聚集成4类
compactness, labels, centers = cv2.kmeans(data, 4, None, criteria, 10, flags)
#图像转换回uint8二维类型
centers = np.uint8(centers)
res = centers[labels.flatten()]
dst = res.reshape((img.shape))

#图像转换为RGB显示
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
dst = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)

#显示图像
titles = ["src","process"]
images = [img, dst]
for i in range(2):
plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray'),
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()

4.运行结果

img

采样 Image Sampling

(项目关键,不过网上讲的不太系统,准备去图书馆转一圈顺便还书

(人工智能安全太遥远了

将一幅连续图像在空间上分割成M×N个网格,每个网格用一个亮度值或灰度值来表示。

图像采样的间隔越大,所得图像像素数越少,空间分辨率越低,图像质量越差,甚至出现马赛克效应;相反,图像采样的间隔越小,所得图像像素数越多,空间分辨率越高,图像质量越好,但数据量会相应的增大。

1.全图采样示例代码

网上的代码存在一个问题,当图像的长度和宽度不能被采样区域整除时,输出图像的最右边和最下边的区域没有被采样处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import cv2
import cv2
import numpy as np
import matplotlib.pyplot as plt

src = cv2.imread("lena.jpg")
height = src.shape[0]
width = src.shape[1]
#height:218 width:220 这里print一下
numHeight = int(height/109)
numWidth = int(width/109)

new_src = np.zeros((height,width,3),np.uint8)

for i in range(109):
y = i*numHeight #数学原理没太懂,希望看到的大佬讲解一下
for j in range(109):
x = j*numWidth
b = src[y,x][0]
g = src[y,x][1]
r = src[y,x][2]
#循环设置小区域采样
for n in range(numHeight):
for m in range(numWidth):
new_src[y+n,x+m][0] = np.uint8(b)
new_src[y+n,x+m][1] = np.uint8(g)
new_src[y+n,x+m][2] = np.uint8(r)

titles = ["src","process"]
images = [src,new_src]
for i in range(2):
plt.subplot(1,2,i+1)
plt.imshow(images[i],'gray')
plt.xticks([]),plt.yticks([])

plt.show()

2.结果

img

(十三)位平面分解

概念

灰度图像中处于统一比特位上的二进制像素值进行组合,得到一副二进制图像,该图像被称为灰度图像的一个位平面,这个过程被称为位平面分解。在组成一张图的过程中,高位的图往往起到了更加关键的作用。

常用的是二进制位平面分解技术(BBD)

img

图示

img

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("lena.png",0)
h , w = img.shape #对应图片的高和长度
x = np.zeros((h,w,8),dtype=np.uint8)
#dtype 返回数据元素的数据类型(int、float等
#uint8保存的数据,是0-255
for i in range(8):
x[:,:,i] = 2 ** i #给8个平面“标号”
r = np.zeros((h,w,8),dtype=np.uint8)
for i in range(8):
r[:,:,i] = cv2.bitwise_and(img,x[:,:,i])
mask = r[:,:,i] > 0
r[mask] = 255
cv2.imwrite("your file path"+str(i)+".png",r[:,:,i])
#cv2.imshow(str(i),r[:,:,i])

cv2.waitKey(0)
cv2.destroyAllWindows()

imgimgimg

imgimgimg

imgimgimg

-------------本文结束感谢您的阅读-------------
请作者喝一杯蜜雪冰城吧!