opencv笔记

数据图像格式

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%;" />

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容