import cv2
# cv2读入图片 cv2.imread('图片的路径')
image = cv2.imread('cat.jpg')
# 显示图片
cv2.imshow('the cat', image)
# 让图片窗口持续显示,没有加此语句,图片会一闪而过
cv2.watiKey(0)
在指定的目录下,会产生新格式的图片文件。
import cv2
# 读入原图
image = cv2.imread('cat.jpg')
# 图片格式转换并存储
cv2.imwrite('cat.png', image)
图片的裁剪用 cv2.resize(InputArray src, OutputArray dst, Size, fx, fy, interpolation)
参数 | 说明 |
---|---|
InputArray src | 输入原图 |
OutputArray dst | 输出图片 |
Size | 输出图片尺寸 |
fx, fy | 沿x轴,y国的缩放系数 |
interpolation | 插入方式 |
interpolation 选项所用的插值方法:
INTER_NEAREST | 最近邻插值 |
---|---|
INTER_LINEAR | 双线性插值(默认设置) |
INTER_AREA | 使用像素区域关系进行重采样 |
INTER_CUBIC | 输出图片尺寸 |
fx, fy | 沿x轴,y国的缩放系数 |
interpolation | 插入方式 |
import cv2
# 双线性插值法
# 读入原图
image = cv2.imread('cat.jpg')
# 获取原图的长、宽,并对应将值存储在x, y
x, y = image.shape[: 2]
# 显示原图
cv2.imshow('Original Picture', image)
# 将图的长宽缩放为原图的三分之一
image_test1 = cv2.resize(image, (int(y / 3), int(x / 3)))
# 显示缩小后的图
cv2.imshow('resize0', image_test1)
# 保存缩小后的图
cv2.imwrite('small_cat.jpg', image_test1)
cv2.waitKey(0)
import cv2
# 读入原图
image = cv2.imread('cat.jpg')
# 显示原图
cv2.imshow('Original Picture', image)
# 将y轴、x轴变为原图的四分之一
image_test2 = cv2.resize(image, (0, 0), fx=0.25, fy=0.25, interpolation=cv2.INTER_NEAREST)
# 显示缩小后的图
cv2.imshow('resize1', image_test2)
# 保存缩小后的图
cv2.imwrite('_0.25_cat.jpg', image_test2)
cv2.waitKey()
cv2.destroyAllWindows()
当我们用 cv2.imread() 读入一幅图时,默认是返回BGR的彩色图片,要返回一个灰度图片,可以在 cv2.imread() 中在传入一个参数 flags=cv2.IMREAD_GRAYSCALE)。
import cv2
# 读入原图,并通过传入 flags 参数,将图转化为灰度图片
image = cv2.imread('C:/Users/77925/Desktop/cat.jpg', flags=cv2.IMREAD_GRAYSCALE)
# 将原图的长宽缩小为原来的0.25倍
test = cv2.resize(image, (0, 0), fx=0.25, fy=0.25)
# 显示缩小后的图
cv2.imshow('test picture', test)
# 保存缩小后的图到指定位置
cv2.imwrite('C:/Users/77925/Desktop/test_cat.jpg', test)
cv2.waitKey()
边缘检测,通俗地说也就是将物体的边缘区域转化为白色或其他颜色,而非边缘区域转化为黑色。opencv 中用于边缘检测的滤波函数有:Laplacian, Sobel, Scharr, Canny等。
在对图片进行边缘检测过程中,容易将噪声错误地识别为边缘,所以在进行边缘检测前,通常进行模糊处理。
opencv中的模糊滤波器有:blur, medianBlur, GausianBlur等。
import cv2
# 读入原图
image = cv2.imread('C:/Users/77925/Desktop/cat.jpg')
# 模糊滤波器
GBlur = cv2.GaussianBlur(image, (3, 3), 0)
# 边缘检测滤波器
canny = cv2.Canny(GBlur, 50, 150)
# 显示图片
cv2.imshow('image', image)
cv2.imshow('canny', canny)
cv2.imwrite('C:/Users/77925/Desktop/cathaha.jpg', canny)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2 as cv
# 读入一张RGB图像
cat = cv.imread('photo\\cat.jpg', cv.IMREAD_UNCHANGED)
# 一次性拆分通道
b, g, r = cv.split(cat)
'''
也可以只拆分单个通道
b = cv.split(cat)[0]
g = cv.split(cat)[1]
r = cv.split(cat)[2]
'''
# 显示拆分通道后的图像,每个通道为一个单通道的灰度图像
cv.imshow('B', b)
cv.imshow('G', g)
cv.imshow('R', r)
cv.imshow('cat', cat)
cv.waitKey(0)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
# 读入一张RGB图像
cat = cv.imread('photo\\cat.jpg', cv.IMREAD_UNCHANGED)
# 拆分通道
b, g, r = cv.split(cat)
# 显示原图像
cv.imshow('original', cat)
# 合并通道,注意合并通道的顺序必须是 b,g,r
m = cv.merge([b, g, r])
# 显示合并后的图像
cv.imshow('result', m)
# 按r,g,b顺序合并图像
rgb = cv.merge([r, g, b])
cv.imshow('rgb', rgb)
# 用某个通道与另外两个全是0的通道合并
# 查看原图像的行列数及通道数
rows, clos, chn = cat.shape
# 拆分出b通道
b = cv.split(cat)[0]
# 生成另外两个全0通道
g = np.zeros([rows, clos], cat.dtype)
r = np.zeros([rows, clos], cat.dtype)
# 合并图像
mm = cv.merge([b, g, r])
# 显示合并后的图像
cv.imshow('mm', mm)
# 其他通道组合类似上边
cv.waitKey(0)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
cat = cv.imread('photo\\cat.jpg', cv.IMREAD_GRAYSCALE)
a = cat
# 用numpy加法
add1 = cat + a
# 用opencv加法
add2 = cv.add(cat, a)
# 显示原图像
cv.imshow('original', cat)
# 用numpy加法的图像
cv.imshow('add1', add1)
# 显示用opencv加法的图像
cv.imshow('add2', add2)
cv.waitKey(0)
cv.destroyAllWindows()
numpy加法与opencv加法的结果是不同的,但在不同的场景下有不同的应用效果。
import cv2 as cv
import numpy as np
a = cv.imread('photo\\1.jpg')
b = cv.imread('photo\\2.jpg')
# 利用cv.addWeighted()函数将两张图融合到一起
result = cv.addWeighted(a, 1, b, 1, -240)
cv.imshow('a', a)
cv.imshow('b', b)
cv.imshow('result', result)
cv.waitKey(0)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
# 读入BGR图像
a = cv.imread('photo\\cat.jpg')
# 将BGR转为灰度图像
b = cv.cvtColor(a, cv.COLOR_BGR2GRAY)
# 将BGR转为RGB
c = cv.cvtColor(a, cv.COLOR_BGR2RGB)
cv.imshow('cat', a)
cv.imshow('gray', b)
cv.imshow('GRB', c)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
# 读入灰度图像
a = cv.imread('photo\\gray.jpg', cv.IMREAD_UNCHANGED)
# 灰度转BGR
b = cv.cvtColor(a, cv.COLOR_GRAY2BGR)
print(b.shape)
'(640, 640, 3),有三个通道'
# 显示BGR图像,看起来是灰色的,但它有3个通道
cv.imshow('BGR', b)
cv.waitKey(-1)
cv.destroyAllWindows()
必备参数:
src:原始图像
dsize:目标图像大小,格式:(列,行)
fx, fy:这个与dsize二选一
import cv2 as cv
import numpy as np
# 读入原始图像
a = cv.imread('photo\\egg.jpg')
# 提取图像的行列数,通道数
rows, cols, chn = a.shape
# size的书写应先列后行,此处的round是为了让列、行数变为整数
size = (round(cols*0.5), round(rows*1))
# 按照新设定的size对原图像进行绽放
b = cv.resize(a, size)
'''
也可采用以下形式对原图像进行绽放,达到的效果是一样的:行一样,列变为原来的一半
当采用此方法时,将desize设置成None即可
b = cv.resize(a, None, fx=0.5, fy=1)
'''
cv.imshow('a', a)
cv.imshow('b', b)
cv.waitKey(-1)
cv.destroyAllWindows()
参数说明:
src:原始图像
flipCode:选择图像翻转的模式
flilpCode>0:左右
flilpCode=0:上下
flilpCode<0:左右+上下
import cv2 as cv
import numpy as np
# 读入原始图像
a = cv.imread('photo\\egg.jpg', cv.IMREAD_UNCHANGED)
# 做上下翻转
b = cv.flip(a, 1)
# 做左右翻转
c = cv.flip(a, 0)
# 做上下+左右翻转
d = cv.flip(a, -1)
# 显示图像
cv.imshow('a', a)
cv.imshow('b', b)
cv.imshow('c', c)
cv.imshow('d', d)
cv.waitKey(-1)
cv.destroyAllWindows()
阈值分割有5种情况:
第一张图是原始图像的像素值。
以下图片的纵轴表示点的像素值,横轴的最底下的线表示最小像素值0,最上边的线表示最大像素值255。
第一种情况:二进制阈值化
第二种情况:反二进制阈值化
第三种情况:截断阈值化
第四种情况:反阈值化为0
第五种情况:阈值化为0
r, b = cv.threshold(a, 127, 255, cv2.THRESH_TOZERO)
import cv2 as cv
# 读入原始图像
a = cv.imread('photo\\ms.jpg', cv.IMREAD_GRAYSCALE)
# 二进制阈值化
r, b = cv.threshold(a, 128, 255, cv.THRESH_BINARY)
# 反二进制阈值化
r2, b2 = cv.threshold(a, 128, 255, cv.THRESH_BINARY_INV)
# 截断阈值化
r3, b3 = cv.threshold(a, 128, 255, cv.THRESH_TRUNC)
# 阈值化为0
r4, b4 = cv.threshold(a, 128, 255, cv.THRESH_TOZERO)
# 反阈值化为0
r5, b5 = cv.threshold(a, 128, 255, cv.THRESH_TOZERO_INV )
cv.imshow('original', a)
cv.imshow('result', b)
cv.imshow('result2', b2)
cv.imshow('result3', b3)
cv.imshow('result4', b4)
cv.imshow('result5', b5)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
# 读入原始图像
a = cv.imread('photo\\ms.jpg')
r = cv.blur(a, (5, 5))
cv.imshow('original', a)
cv.imshow('result', r)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
a = cv.imread('C:\\Users\\77925\\Desktop\\photo\\cat.jpg')
# 使用方框滤波对图像进行处理,当normalize=1(默认)时,进行归一化处理
r = cv.boxFilter(a, -1, (5, 5), normalize=1)
# 不进行归一化处理,normalize=0
r2 = cv.boxFilter(a, -1, (2, 2), normalize=0)
cv.imshow('original', a)
cv.imshow('result', r)
cv.imshow('result2', r2)
cv.waitKeyEx(-1)
cv.destroyAllWindows()
一般情况下设 sigmaX=0,函数会根据核的大小自动计算方差做为权重
处理效果如下:能将一些小点给模糊化
import cv2 as cv
a = cv.imread('C:\\Users\\77925\\Desktop\\photo\\cats.jpg')
# 高斯滤波
r = cv.GaussianBlur(a, (5, 5), 0)
cv.imshow('original', a)
cv.imshow('result', r)
cv.waitKeyEx(-1)
cv.destroyAllWindows()
将核里的像素值按顺序排列,取中间的值做为新的像素值。
ksize:核的大小 ,用一个数字表示即可,比如3,它表示核的大小为3*3
中值滤波的处理效果如下:
import cv2 as cv
a = cv.imread('C:\\Users\\77925\\Desktop\\photo\\cats.jpg')
# 中值滤波
r = cv.medianBlur(a, 3)
cv.imshow('original', a)
cv.imshow('result', r)
cv.waitKeyEx(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\ms01.jpg', cv.IMREAD_UNCHANGED)
# 建立一个5*5的核
k = np.ones((5, 5), np.uint8)
# 进行腐蚀,iterations=2,表示进行2次腐蚀操作,流程图时默认为1次
r = cv.erode(o, k, iterations=2)
#显示图像
cv.imshow('original', o)
cv.imshow('result', r)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\ms01.jpg', cv.IMREAD_UNCHANGED)
# 建立一个5*5的核
k = np.ones((5, 5), np.uint8)
# 进行膨胀
r = cv.dilate(o, k, iterations=1)
#显示图像
cv.imshow('original', o)
cv.imshow('result', r)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\CAD01.jpg', cv.IMREAD_UNCHANGED)
# 建立核
k = np.ones((15, 15), np.uint8)
# 进行开运算
r = cv.morphologyEx(o, cv.MORPH_OPEN, k)
cv.imshow('original', o)
cv.imshow('result', r)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\CAD2.jpg', cv.IMREAD_UNCHANGED)
# 建立核
k = np.ones((30, 30), np.uint8)
# 进行开运算
r = cv.morphologyEx(o, cv.MORPH_CLOSE, k)
cv.imshow('original', o)
cv.imshow('result', r)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\CAD.jpg', cv.IMREAD_UNCHANGED)
# 建立核
k = np.ones((3, 3), np.uint8)
# 梯度操作
r = cv.morphologyEx(o, cv.MORPH_GRADIENT, k)
cv.imshow('original', o)
cv.imshow('result', r)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\CAD3.jpg', cv.IMREAD_UNCHANGED)
# 建立核
k = np.ones((3, 3), np.uint8)
# 礼帽运算
r = cv.morphologyEx(o, cv.MORPH_TOPHAT, k)
cv.imshow('original', o)
cv.imshow('result', r)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\CAD2.jpg', cv.IMREAD_UNCHANGED)
# 建立核
k = np.ones((10, 10), np.uint8)
# 黑帽操作
r = cv.morphologyEx(o, cv.MORPH_BLACKHAT, k)
cv.imshow('original', o)
cv.imshow('result', r)
cv.waitKey(-1)
cv.destroyAllWindows()
sobel 用于计算不同方向的梯度
计算P5点X方向的梯度
如果P5值比较大,那P5可以认为 一个边界,如果P5比较小,可以认为这里不是边界。
整个图像的梯度
作用:将负数的值取绝对值
一般这样写就可以了
dx:表示计算X轴方向的边界,dy:表示计算Y轴方向的边界
方式2更严谨
ksize:一般不用,如果用的话可以设置成奇数,不用的话默认是3*3的核。
将ddepth设置为-1时,只取到像素差为正数的部分,像素差为负数的部分不显示,结果如下图
ddepth=cv.CV_64F,保留了差值为负数的部分,但仍会被处理为0,所以结果仍然没有显示负数部分。
sobelx = cv2.convertScaleAbs(sobels)的作用,差负数转为正数。
将X Y 轴一起计算
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\Enpro.jpg', cv.IMREAD_GRAYSCALE)
# sobel算子,计算X轴方向的梯度
sobelx = cv.Sobel(o, cv.CV_64F, 1, 0)
# 将负数部分取绝对值
sobelx = cv.convertScaleAbs(sobelx)
# y轴方向的梯度
sobely = cv.Sobel(o, cv.CV_64F, 0, 1)
# 取绝对值
sobely = cv.convertScaleAbs(sobely)
# 将x,y轴的梯度相加
sobelxy = cv.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
# 直接同时计算x,y轴的情况
sobelxy11 = cv.Sobel(o, cv.CV_64F, 1, 1)
# 取绝对值
sobelxy11 = cv.convertScaleAbs(sobelxy11)
cv.imshow('original', o)
cv.imshow('sobelx', sobelx)
cv.imshow('sobely', sobely)
cv.imshow('sobelxy', sobelxy)
cv.imshow('sobelxy11', sobelxy11)
cv.waitKey(-1)
cv.destroyAllWindows()
ddepth的情况与Sobel算子情况类似。
dx和dy不能同时为1
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\Enpro.jpg', cv.IMREAD_GRAYSCALE)
# scharry算子,计算X轴方向的梯度
scharrx = cv.Scharr(o, cv.CV_64F, 1, 0)
# 将负数部分取绝对值
Scharrx = cv.convertScaleAbs(scharrx)
# y轴方向的梯度
Scharry = cv.Scharr(o, cv.CV_64F, 0, 1)
# 取绝对值
Scharry = cv.convertScaleAbs(Scharry)
# 将x,y轴的梯度相加
Scharrxy = cv.addWeighted(Scharrx, 0.5, Scharry, 0.5, 0)
cv.imshow('original', o)
cv.imshow('Scharrx', Scharrx)
cv.imshow('Scharry', Scharry)
cv.imshow('Scharrxy', Scharrxy)
cv.waitKey(-1)
cv.destroyAllWindows()
如果将sobel算子的第五个参数设置为-1,功能与scharr算子相同,代码如下:
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\Enpro.jpg', cv.IMREAD_GRAYSCALE)
# sobel算子的第5个参数设为-1,相当于scharr算子
scharrx = cv.Sobel(o, cv.CV_64F, 1, 0, -1)
# 将负数部分取绝对值
Scharrx = cv.convertScaleAbs(scharrx)
# sobel算子的第5个参数设为-1,相当于scharr算子
Scharry = cv.Sobel(o, cv.CV_64F, 0, 1, -1)
# 取绝对值
Scharry = cv.convertScaleAbs(Scharry)
# 将x,y轴的梯度相加
Scharrxy = cv.addWeighted(Scharrx, 0.5, Scharry, 0.5, 0)
cv.imshow('original', o)
cv.imshow('Scharrx', Scharrx)
cv.imshow('Scharry', Scharry)
cv.imshow('Scharrxy', Scharrxy)
cv.waitKey(-1)
cv.destroyAllWindows()
两者的卷积核大小是一样的,两都的计算量和计算速度是一样的。
不同之处在于,scharr算子的左右系数比sobel算子的系数大,当两边的像素数值一样的情况下,以竖直方向为例:
设右边的像素为a,左边的像素为b,在计算两边的差值时,sobel算子的差值为2*(a-b),而scharr算子的差值为10*(a-b),相较这下,scharr算子的差值会更大,精确度也会更高。
以下对两者的效果做下对比
import cv2 as cv
import numpy as np
# 读入原始图像
o = cv.imread('photo\\ms.jpg', cv.IMREAD_GRAYSCALE)
# sobel算子
sobelx = cv.Sobel(o, cv.CV_64F, 1, 0)
sobelx = cv.convertScaleAbs(sobelx)
sobely = cv.Sobel(o, cv.CV_64F, 0, 1)
sobely = cv.convertScaleAbs(sobely)
sobelxy = cv.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
cv.imshow('original', o)
cv.imshow('sobelxy', sobelxy)
# scharr算子
scharrx = cv.Scharr(o, cv.CV_64F, 1, 0)
scharrx = cv.convertScaleAbs(scharrx)
scharry = cv.Scharr(o, cv.CV_64F, 0, 1)
scharry = cv.convertScaleAbs(scharry)
scharrxy = cv.addWeighted(scharrx, 0.5, scharry, 0.5, 0)
cv.imshow('schaarxy', scharrxy)
cv.waitKey(-1)
cv.destroyAllWindows()
可以看到,用scharr算子,结果更加精细,但使用哪一种看具体情况。
import cv2 as cv
o = cv.imread('C:\\Users\\77925\\Desktop\\photo\\NBA.jpg')
# laplacian算子
r = cv.Laplacian(o, cv.CV_64F)
# 将负数部分取绝对值
r = cv.convertScaleAbs(r)
cv.imshow('original', o)
cv.imshow('result', r)
cv.waitKeyEx(-1)
cv.destroyAllWindows()
![在这里插入图片描述](https://img-blog.csdnimg.cn/202003172237565
import cv2 as cv
# 读入图像
o = cv.imread('C:\\Users\\77925\\Desktop\\photo\\house.jpg')
# 进行canny边缘检测
r = cv.Canny(o, 100, 200)
# 将canny阈值调小
r2 = cv.Canny(o, 50, 100)
# 显示图像
cv.imshow('original', o)
cv.imshow('result', r)
cv.imshow('result2', r2)
cv.waitKeyEx(-1)
cv.destroyAllWindows()
向上或者向下取样,针对的是图像的像素大小,向上取样,像素增大,向下取样,像素减小。
import cv2 as cv
# 读入图像
o = cv.imread('C:\\Users\\77925\\Desktop\\photo\\house.jpg')
# 向下取样
r = cv.pyrDown(o)
# 显示图像
cv.imshow('original', o)
cv.imshow('result', r)
cv.waitKeyEx(-1)
cv.destroyAllWindows()
经过向下取样,再向上取样,虽然图像大小是一样的,但是变模糊了,这是因为在向下取样时,图像的部分信息已经丢失了。
先向下取样,再向上取样
import cv2 as cv
# 读入图像
o = cv.imread('C:\\Users\\77925\\Desktop\\photo\\cat.jpg')
# 向下取样
rd = cv.pyrDown(o)
# 向上取样
rdu = cv.pyrUp(rd)
# 显示图像
cv.imshow('original', o)
cv.imshow('rd', rd)
cv.imshow('rdu', rdu)
cv.waitKeyEx(-1)
cv.destroyAllWindows()
先向上取样,再向下取样
import cv2 as cv
# 读入图像
o = cv.imread('C:\\Users\\77925\\Desktop\\photo\\cat.jpg')
# 向上取样
ru = cv.pyrUp(o)
# 向下取样
rud = cv.pyrDown(ru)
# 显示图像
cv.imshow('original', o)
cv.imshow('ru', ru)
cv.imshow('rud', rud)
cv.waitKeyEx(-1)
cv.destroyAllWindows()
可以看到,无论以哪种顺序进行,最终得到的图像都会变模糊,说明这个过程是不可逆的。
import cv2 as cv
# 读入原始图像
o = cv.imread('photo\\me.jpg', cv.IMREAD_GRAYSCALE)
# 向下取样
od = cv.pyrDown(o)
# 向上取样
odu = cv.pyrUp(od)
# 第一层
layPyr = o - odu
# 第二层
o1 = od
odd = cv.pyrDown(o1)
oddu = cv.pyrUp(odd)
layPyr1 = o1 - oddu
print(o1.shape)
print(oddu.shape)
cv.imshow('original', o)
cv.imshow('laplacian', layPyr)
cv.imshow('laplacian1', layPyr1)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
# 读入RGB原始图像
o = cv.imread('photo\\Enpro.jpg')
# 将原始图像转为灰度图像
gray = cv.cvtColor(o, cv.COLOR_BGR2GRAY)
# 对灰度图像进行二值化操作
ret, binary = cv.threshold(gray, 128, 255, cv.THRESH_BINARY)
# 查找图像的轮廓信息
contours, hierarchy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# 因为会改变原始图像,所以用备份图像进行操作
co = o.copy()
# 绘制轮廓信息,参数-1表示绘制所有图像的轮廓,也可以用0, 1, 2,....等索引
r = cv.drawContours(co, contours, -1, (0, 0, 255), 5)
cv.imshow('original', o)
cv.imshow('result', r)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
import matplotlib.pyplot as plt
# 读入RGB原始图像
o = cv.imread('photo\\NBA.jpg')
cv.imshow('original', o)
# 将二维数组转为一维
a = o.ravel()
# 绘制直方图
b = plt.hist(o.ravel(), 256)
plt.show(b)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 读入RGB原始图像
o = cv.imread('photo\\NBA.jpg')
# 获取RGB图像三个通道的直方图信息
histb = cv.calcHist([o], [0], None, [256], [0, 255])
histg = cv.calcHist([o], [1], None, [256], [0, 255])
histr = cv.calcHist([o], [2], None, [256], [0, 255])
# 绘制直方图
b = plt.plot(histb, c='b')
g = plt.plot(histg, c='g')
r = plt.plot(histr, c='r')
cv.imshow('NBA', o)
plt.show(b)
plt.show(g)
plt.show(r)
cv.waitKey(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 读入原始图像
o = cv.imread('photo\\NBA.jpg')
# 掩膜,如果原图像是GRB图像,这里用o.shape[0: 2]
# 如果是灰度图像,用o.shape即可
m = np.zeros(o.shape[0: 2], np.uint8)
m[200: 400, 200: 400] = 255
# 收集直方图信息
histO = cv.calcHist([o], [0], None, [256], [0, 255])
histM = cv.calcHist([o], [0], m, [256], [0, 255])
# 显示直方图
plt.plot(histO)
plt.plot(histM)
plt.show()
cv.waitKeyEx(-1)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 读入原始图像
o = cv.imread('photo\\NBA.jpg', cv.IMREAD_GRAYSCALE)
# 掩膜图像
m = np.zeros(o.shape, np.uint8)
m[100: 200, 100: 300] = 255
# 生成掩膜图像
mo = cv.bitwise_and(o, m)
cv.imshow('original', o)
cv.imshow('mask', m)
cv.imshow('mo', mo)
cv.waitKeyEx(-1)
cv.destroyAllWindows()
import cv2 as cv
import matplotlib.pyplot as plt
# 读入原始图像
o = cv.imread('photo\\try.jpg', cv.IMREAD_GRAYSCALE)
# 直方图均衡处理
r = cv.equalizeHist(o)
cv.imshow('original', o)
cv.imshow('result', r)
# 绘制直方图
plt.hist(r.ravel(), 256)
plt.figure()
plt.hist(o.ravel(), 256)
plt.show()
cv.waitKeyEx(-1)
cv.destroyAllWindows()
从以上两幅直方图可以看到,经过处理后的直方图,分布更加均衡。
import cv2 as cv
import matplotlib.pyplot as plt
# 读入原始图像
o = cv.imread('photo\\NBA.jpg', cv.IMREAD_GRAYSCALE)
# 直方图均衡处理
e = cv.equalizeHist(o)
# 绘制直方图
plt.subplot(1, 2, 1)
plt.hist(o.ravel(), 256)
plt.subplot(1, 2, 2)
plt.hist(e.ravel(), 256)
plt.show()
import cv2 as cv
import matplotlib.pyplot as plt
# 读入原始图像
o = cv.imread('photo\\cat.jpg')
# 转为灰度图像
g = cv.cvtColor(o, cv.COLOR_BGR2GRAY)
# 显示图像
# 用默认值显示彩色图像
plt.subplot(221)
plt.imshow(o)
plt.axis('off')
# 用灰度值显示彩色图像
plt.subplot(222)
plt.imshow(o, cmap=plt.cm.gray)
plt.axis('off')
# 用默认值显示灰度图像
plt.subplot(223)
plt.imshow(g)
plt.axis('off')
# 用灰度值显示灰度图像
plt.subplot(224)
plt.imshow(g, cmap=plt.cm.gray)
plt.axis('off')
plt.show()
结果显示,只有传入的图像为灰度图像,并显式地写出 cmap=plt.cm.gray时,才能正确地显示灰度图像。
import cv2 as cv
import matplotlib.pyplot as plt
# 读入原始图像
o = cv.imread('photo\\cat.jpg')
# 获取图像的三个通道
b, g, r = cv.split(o)
# 对三个通道进行重新组合
o2 = cv.merge([r, g, b])
# 显示图像
plt.subplot(121)
plt.imshow(o)
plt.axis('off')
plt.subplot(122)
plt.imshow(o2)
plt.axis('off')
plt.show()
import cv2 as cv
import matplotlib.pyplot as plt
# 读入原始图像
o = cv.imread('photo\\NBA.jpg', cv.IMREAD_GRAYSCALE)
# 直方图均衡化
e = cv.equalizeHist(o)
# 显示图像及对应的直方图
plt.subplot(221)
plt.imshow(o, cmap=plt.cm.gray)
plt.axis('off')
plt.subplot(222)
plt.imshow(e, cmap=plt.cm.gray)
plt.axis('off')
plt.subplot(223)
plt.hist(o.ravel(), 256)
plt.subplot(224)
plt.hist(e.ravel(), 256)
plt.show()
白色但表低频,为了观看更直观,一般将其移至中心。
复数的数组是没法通过图像的形式展现出来的,我们需要将其转换为灰度图像,所以需要将复数的值映射到[0, 255],这个函数实现数据的映射。
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 读入原始图像
o = cv.imread('photo\\NBA.jpg', 0)
# 傅里叶变换
f = np.fft.fft2(o)
# 将低频谱移动到中心位置
fshift = np.fft.fftshift(f)
# 数据映射
result = 20 * np.log(np.abs(fshift))
# 显示图像
plt.subplot(121)
plt.imshow(o, cmap='gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(result, cmap='gray')
plt.title('result')
plt.axis('off')
plt.show()
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 读入原始图像
o = cv.imread('photo\\NBA.jpg', 0)
# 傅里叶变换
f = np.fft.fft2(o)
# 将低频移动到中心位置
fshift = np.fft.fftshift(f)
# 将低频由中心移至左上角
ishift = np.fft.ifftshift(fshift)
# 逆傅里叶变换
io = np.fft.ifft2(ishift)
# 数据映射
io = np.abs(io)
# 显示图像
plt.subplot(121)
plt.imshow(o, cmap='gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(io, cmap='gray')
plt.title('result')
plt.axis('off')
plt.show()
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
o = cv.imread('photo\\house.jpg', 0)
# 傅里叶变换
f = np.fft.fft2(o)
fshift = np.fft.fftshift(f)
# 高通滤波器
rows, cols = o.shape
crow, ccol = int(rows/2), int(cols/2)
fshift[crow-25: crow+25, ccol-25: ccol+25] = 0
# 逆傅里叶变换
ishift = np.fft.ifftshift(fshift)
io = np.fft.ifft2(ishift)
io = np.abs(io)
# 显示图像
plt.subplot(121)
plt.imshow(o, cmap='gray')
plt.axis('off')
plt.subplot(122)
plt.imshow(io, cmap='gray')
plt.axis('off')
plt.show()
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
o = cv.imread('photo\\house.jpg', 0)
# 傅里叶变换,并将原始图像转换为float32格式
dft = cv.dft(np.float32(o), flags=cv.DFT_COMPLEX_OUTPUT)
# 将低频部分转换到中心
dshift = np.fft.fftshift(dft)
# 数值转换,两个帽号分别表示行和列,0和1分别表示两个通道
result = 20 * np.log(cv.magnitude(dshift[:, :, 0], dshift[:, :, 1]))
# 显示图像
plt.subplot(121)
plt.imshow(o, cmap='gray')
plt.axis('off')
plt.subplot(122)
plt.imshow(result, cmap='gray')
plt.axis('off')
plt.show()
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
o = cv.imread('photo\\house.jpg', 0)
# 傅里叶变换,并将原始图像转换为float32格式
dft = cv.dft(np.float32(o), flags=cv.DFT_COMPLEX_OUTPUT)
# 将低频部分转换到中心
dshift = np.fft.fftshift(dft)
# 将低频部分移回左上角
ishift = np.fft.ifftshift(dshift)
# 逆傅里叶变换
io = cv.idft(ishift)
# 数值转换
io = cv.magnitude(io[:, :, 0], io[:, :, 1])
# 显示图像
plt.subplot(121)
plt.imshow(o, cmap='gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(io, cmap='gray')
plt.title('result')
plt.axis('off')
plt.show()
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
o = cv.imread('photo\\house.jpg', 0)
# 傅里叶变换
dft = cv.dft(np.float32(o), flags=cv.DFT_COMPLEX_OUTPUT)
# 将低频部分转到中心
dshift = np.fft.fftshift(dft)
# 计算掩膜图像
rs, cs = o.shape
cr, cc = int(rs/2), int(cs/2)
mask = np.zeros((rs, cs, 2), np.int8)
mask[cr-30: cr+30, cc-30: cc+30] = 1
md = dshift * mask
# 逆傅里叶变换
imd = np.fft.ifftshift(md)
io = cv.idft(imd)
io = cv.magnitude(io[:, :, 0], io[:, :, 1])
# 显示图像
plt.subplot(121)
plt.imshow(o, cmap='gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(io, cmap='gray')
plt.title('result')
plt.axis('off')
plt.show()