opencv笔记

2022-04-18  本文已影响0人  v587的毅哥

数据图像格式

cv2.IMREAD_COLOR: 彩色图像
cv2.IMREAD_GRAYSCALE: 灰度图像

读取图像方法

img = cv2.imread('cat.jpg')

输出图像

img

[out]:
#[h,w,c]
array([
[[100,100,100],[200,200,200],[300,300,300]…,[900,900,900]],
[[111,111,111],[222,222,222],[333,333,333]…,[999,999,999]],
[[123,123,123],[234,234,234],[345,345,345]…,[789,789,789]]
],dtype=unit8)

显示图像

cv2.imshow('image_name',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像数据大小与格式

img.shape

[out]:
(414,500,3)
#也就是上面的[h,w,c],c就是代表BGR

读取为灰度图

img = cv2.imread('cat.jpg',cv2.IMREAD_GRAYSCALE)
img

[out]:
array([
[100,200,300,…,900],
[111,222,333,…,999],
…
[123,456,789,…,012]
],dtype=unit8)

保存图像

cv2.imwrite('mycat.png',img)

查看图像的格式

type(img)

[out]:numpy.ndarray

查看图像的大小

img.size

[out]:
207000

查看图像的dtype

img.dtype

[out]:
dype('unit8')

读取视频

cv2.VideoCapture可以捕获摄像头,用数字来控制不同的设备,例如0,1。
如果是视频文件,直接指定好路径即可。

vc = cv2.VideoCapture('test.mp4')
# 检查是否打开正确
if vc.isOpened(): 
    open, frame = vc.read()
else:
    open = False
#%%
while open:
    ret, frame = vc.read()
    if frame is None:
        break
    if ret == True:
        gray = cv2.cvtColor(frame,  cv2.COLOR_BGR2GRAY)
        cv2.imshow('result', gray)
        if cv2.waitKey(100) & 0xFF == 27:
            break
vc.release()
cv2.destroyAllWindows()

截取部分图像数据

img = cv2.imread('cat.jpg`)
cat = img[0:200,0:200]
cv_show('cat',cat)

颜色通道提取

b,g,r = cv2.split(img)
b

[out]:
array([[160, 164, 169, ..., 185, 184, 183],
       [126, 131, 136, ..., 184, 183, 182],
       [127, 131, 137, ..., 183, 182, 181],
       ...,
       [198, 193, 178, ..., 206, 195, 174],
       [176, 183, 175, ..., 188, 144, 125],
       [190, 190, 157, ..., 200, 145, 144]], dtype=uint8)

颜色的合并

img = cv2.merge((b,g,r))

只保留R(其余通道置为0)

cur_img = img.copy()
cur_img[:,:,0] = 0
cur_img[:,:,1] = 0
cv_show('R',cur_img)

边界填充(周围扩大一圈)

# 先定义一下填充的大小
top_size,bottom_size,left_size,right_size = (50,50,50,50)
# 不同的填充方法
replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)

<img src="http://img.yibogame.com/uPic/2022-04-18-21-54-56-1650290096178-2022-04-18-18-58-55-1650279535945-output.png" alt="image-20220418205212143" />
BORDER_REPLICATE:复制法,也就是复制最边缘像素。
BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb
BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba
BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg
BORDER_CONSTANT:常量法,常数值填充。

数值计算

img_cat = cv2.imread('cat.jpg')
img_dog = cv2.imread('dog.jpg')
img_cat[:5,:,0]
[out]:
array([[142, 146, 151, ..., 156, 155, 154],
       [107, 112, 117, ..., 155, 154, 153],
       [108, 112, 118, ..., 154, 153, 152],
       [139, 143, 148, ..., 156, 155, 154],
       [153, 158, 163, ..., 160, 159, 158]], dtype=uint8)
img_cat2= img_cat +10 
img_cat[:5,:,0]
[out]:
array([[152, 156, 161, ..., 166, 165, 164],
       [117, 122, 127, ..., 165, 164, 163],
       [118, 122, 128, ..., 164, 163, 162],
       [149, 153, 158, ..., 166, 165, 164],
       [163, 168, 173, ..., 170, 169, 168]], dtype=uint8)
#相当于 %(取余) 256
(img_cat + img_cat2)[:5,:,0] 
[out]:
array([[ 38,  46,  56, ...,  66,  64,  62],
       [224, 234, 244, ...,  64,  62,  60],
       [226, 234, 246, ...,  62,  60,  58],
       [ 32,  40,  50, ...,  66,  64,  62],
       [ 60,  70,  80, ...,  74,  72,  70]], dtype=uint8)
cv2.add(img_cat,img_cat2)[:5,:,0]
[out]:
array([[255, 255, 255, ..., 255, 255, 255],
       [224, 234, 244, ..., 255, 255, 255],
       [226, 234, 246, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], dtype=uint8)

图像融合

img_cat + img_dog

[out]:
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-111-ffa3cdc5d6b8> in <module>()
----> 1 img_cat + img_dog

ValueError: operands could not be broadcast together with shapes (414,500,3) (429,499,3)

因为两个大小不一样,报错了!那先看看img_cat的大小:
img_cat.shape

[out]:
(414, 500, 3)

把狗变为猫那么大:

img_dog = cv2.resize(img_dog, (500, 414))
img_dog.shape
[out]:
(414, 500, 3)
# Result = αx1 + βx2 + b(x1:猫,x2:狗,b:偏移量,α、β:权重)
res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0)
plt.imshow(res)

<img src="http://img.yibogame.com/uPic/2022-04-18-18-58-49-1650279529590-output1.png" alt="image-20220418205212143" />

图像阈值处理

ret, dst = cv2.threshold(src, thresh, maxval, type)
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
thresh: 阈值
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
type:二值化操作的类型,包含以下5种类型:

cv2.THRESH_TOZERO_INV
cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
cv2.THRESH_BINARY_INVTHRESH_BINARY的反转
cv2.THRESH_TRUNC大于阈值部分设为阈值,否则不变
cv2.THRESH_TOZERO大于阈值部分不改变,否则设为0
cv2.THRESH_TOZERO_INVTHRESH_TOZERO的反转

ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

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()

<img src="http://img.yibogame.com/uPic/2022-04-18-18-58-44-1650279524214-output3.png" alt="image-20220418205212143" />

图像平滑处理

<img src="http://img.yibogame.com/uPic/2022-04-18-18-58-37-1650279517969-input1.png" alt="input1" style="zoom:50%;" />

img = cv2.imread('lenaNoise.png')

原始带噪点图像:
<img src="http://img.yibogame.com/uPic/2022-04-18-20-49-04-1650286144073-lenaNoise.png" alt="lenaNoise" style="zoom:50%;" />

# 均值滤波(121+75+78+……+235)/9
# 简单的平均卷积操作
blur = cv2.blur(img, (3, 3))
cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

均值滤波输出的结果:
<img src="http://img.yibogame.com/uPic/2022-04-18-20-52-12-1650286332261-image-20220418205212143.png" alt="image-20220418205212143" style="zoom: 25%;" />

# 方框滤波
# 基本和均值一样,可以选择归一化(与上图一样)
box = cv2.boxFilter(img,-1,(3,3), normalize=True)  
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()

方框滤波输出的结果(归一化):
<img src="http://img.yibogame.com/uPic/2022-04-18-20-52-12-1650286332261-image-20220418205212143.png" alt="image-20220418205212143" style="zoom: 25%;" />

# 方框滤波
# 基本和均值一样,可以选择归一化,容易越界(超过255。当超过255后就是255)
box = cv2.boxFilter(img,-1,(3,3), normalize=False)  
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()

方框滤波输出的结果(不归一化):
<img src="http://img.yibogame.com/uPic/2022-04-18-20-55-19-1650286519100-image-20220418205518999.png" alt="image-20220418205518999" style="zoom: 25%;" />

# 高斯滤波
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian = cv2.GaussianBlur(img, (5, 5), 1)  

cv2.imshow('aussian', aussian)
cv2.waitKey(0)
cv2.destroyAllWindows()

高斯滤波的函数图像:
<img src="http://img.yibogame.com/uPic/2022-04-18-21-04-07-1650287047640-image-20220418210407535.png" alt="image-20220418210407535" style="zoom:50%;" />

高斯滤波的卷积核大概类似于这样(越中间影响越大):
<img src="http://img.yibogame.com/uPic/2022-04-18-21-01-58-1650286918084-image-20220418210157986.png" alt="image-20220418210157986" style="zoom:50%;" />

高斯滤波输出的结果:
<img src="http://img.yibogame.com/uPic/2022-04-18-20-59-36-1650286776559-image-20220418205936456.png" alt="image-20220418205936456" style="zoom:25%;" />

# 中值滤波(把121,75,78,……,235按数值大小排序,再取中间的那个值)
# 相当于用中值代替
median = cv2.medianBlur(img, 5)  # 中值滤波

cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()

中值滤波输出的结果:
<img src="http://img.yibogame.com/uPic/2022-04-18-21-09-00-1650287340845-image-20220418210900722.png" alt="image-20220418210900722" style="zoom:25%;" />

# 展示所有的
res = np.hstack((blur,aussian,median))
# 垂直展示也行:
# res = np.vstack((blur,aussian,median))
cv2.imshow('median vs average', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

hstack方式输出结果:

<img src="http://img.yibogame.com/uPic/2022-04-18-21-16-04-1650287764298-image-20220418211604185.png" alt="image-20220418211604185" style="zoom:25%;" />

形态学----腐蚀(erode)

img = cv2.imread('res/dige.png')

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

原始图像:
<img src="http://img.yibogame.com/uPic/2022-04-18-21-25-15-1650288315808-image-20220418212515704.png" alt="image-20220418212515704" style="zoom:35%;" />

#3*3的卷积核
kernel = np.ones((3, 3), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)

cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

腐蚀后的图像:
<img src="http://img.yibogame.com/uPic/2022-04-18-21-25-37-1650288337151-image-20220418212537049.png" alt="image-20220418212537049" style="zoom:35%;" />

pie = cv2.imread('res/pie.png')

cv2.imshow('pie', pie)
cv2.waitKey(0)
cv2.destroyAllWindows()

腐蚀卷积核:
<img src="http://img.yibogame.com/uPic/2022-04-18-21-38-46-1650289126077-image-20220418213845958.png" alt="image-20220418213845958" style="zoom:35%;" />

#30*30的卷积核
kernel = np.ones((30, 30), np.uint8)
#腐蚀1、2、3次
erosion_1 = cv2.erode(pie, kernel, iterations=1)
erosion_2 = cv2.erode(pie, kernel, iterations=2)
erosion_3 = cv2.erode(pie, kernel, iterations=3)
res = np.hstack((erosion_1, erosion_2, erosion_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

腐蚀1、2、3次的结果图:
<img src="http://img.yibogame.com/uPic/2022-04-18-21-39-49-1650289189888-image-20220418213949773.png" alt="image-20220418213949773" style="zoom:35%;" />

形态学----膨胀(dilate)

img = cv2.imread('res/dige.png')
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

原始图像:
<img src="http://img.yibogame.com/uPic/2022-04-18-21-25-15-1650288315808-image-20220418212515704.png" alt="image-20220418212515704" style="zoom:35%;" />

# 先腐蚀一次
kernel = np.ones((3, 3), np.uint8)
dige_erosion = cv2.erode(img, kernel, iterations=1)

cv2.imshow('dige_erosion', dige_erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

腐蚀后输出图像(减肥):
<img src="http://img.yibogame.com/uPic/2022-04-18-21-25-37-1650288337151-image-20220418212537049.png" alt="image-20220418212537049" style="zoom:35%;" />

# 再膨胀一次
kernel = np.ones((3, 3), np.uint8)
dige_dilate = cv2.dilate(dige_erosion, kernel, iterations=1)

cv2.imshow('dilate', dige_dilate)
cv2.waitKey(0)
cv2.destroyAllWindows()

膨胀后输出图像(增肥):
<img src="http://img.yibogame.com/uPic/2022-04-18-21-49-44-1650289784890-image-20220418214944784.png" alt="image-20220418214944784" style="zoom:35%;" />

# 原图就不展示了,就是上面那个圆
pie = cv2.imread('res/pie.png')

kernel = np.ones((30, 30), np.uint8)
dilate_1 = cv2.dilate(pie, kernel, iterations=1)
dilate_2 = cv2.dilate(pie, kernel, iterations=2)
dilate_3 = cv2.dilate(pie, kernel, iterations=3)
res = np.hstack((dilate_1, dilate_2, dilate_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

<img src="http://img.yibogame.com/uPic/2022-04-18-21-52-02-1650289922866-image-20220418215202759.png" alt="image-20220418215202759" style="zoom:50%;" />

上一篇 下一篇

猜你喜欢

热点阅读