Opencv图像基础操作

图像基础操作

  1. 图像在numpy.ndarray中的结构
    首先我们需要创建一幅2×2的3颜色通道图像:
#创建一幅2×2的3颜色通道图像,其中数字代表像素,np.uint8是numpy数据类型[0,255]
img = np.array([[[0,1,2],[3,4,5]],[[6,7,8],[9,10,11]]],np.uint8)
#查看图像numpy.ndarray中的结构
print(img)
#查看图像的行、列、颜色通道(BGR)
print(img.shape)
#在蓝色通道中,第1行第1列的像素
print(img[0,0,0])
#在蓝色通道中,第1行第2列的像素
print(img[0,1,0])
#在蓝色通道中,第2行第1列的像素
print(img[1,0,0])
#在绿色通道中,第1行第1列的像素
print(img[0,0,1])
#在红色通道中,第1行第1列的像素
print(img[0,0,2])
#3通道中,第1行第1列的像素
print(img[0,0])
[[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]]
(2, 2, 3)
0
3
6
1
2
[0 1 2]

其中在蓝通道B中,0,3代表第一行,6,9代表第二行,如下图所示

绘图4.jpg.jpeg

2.图像属性

图像的属性包括:行,列,通道,图像数据类型,像素数目等

在opencv中,图像不是传统的RGB颜色通道,而是按BGR顺序存储的。

img_BGR = cv2.imread('citrus-fruit-colorful-delicious-2146386.jpg') 
print(type(img_BGR)) # numpy.ndarray类型可以用numpy对图像进行各种操作
print(img_BGR.dtype) # 图像数据类型,一张图片的像素值范围是[0,255], 因此默认类型是unit8
print(img_BGR.shape[0]) # 行
print(img_BGR.shape[1]) # 列
print(img_BGR.shape[2]) # 通道
print(img_BGR.size) # 像素数目
print(img_BGR.max()) # 最大像素值
print(img_BGR.min()) # 最小像素值
print(img_BGR.mean()) #素值平均值
<class 'numpy.ndarray'>
uint8
4864
3648
3
53231616
255
0
211.1315848273327

3.获取并修改像素值

根据像素的行和列的坐标获取他的像素值。

img = cv2.imread("art-art-exhibition-art-gallery-2110950.jpg")
px = img[100,100] # BGR3个通道中,第100行第100列的像素
print(px)
blue = img[100,100,0]# B通道中,第100行第100列的像素
print(blue)
[215 215 199]
215

修改像素值

img = cv2.imread("art-art-exhibition-art-gallery-2110950.jpg")
img[100,100]=[255,255,255]
print(img[100,100])
[255 255 255]

例子:使大于150的像素等于255(即使灰色像素变为白色)

img = cv2.imread("art-art-exhibition-art-gallery-2110950.jpg")
# 使大于150的像素等于255
img[img>150]=255
cv2.imwrite('img150.jpg',img)
img150.jpg

4.图像 ROI

有时你需要对一幅图像的特定区域进行操作。例如我们要检测一副图像中眼睛的位置,我们首先应该在图像中找到脸,再在脸的区域中找眼睛,而不是直接在一幅图像中搜索。这样会提高程序的准确性和性能。

ROI 也是使用 Numpy 索引来获得的。

例子:获取图像区域像素(即裁剪)

img = cv2.imread("art-art-exhibition-art-gallery-2110950.jpg")
px = img[700:2700,1200:3900] # 获取第700-2700行、第1200-3900列的像素
cv2.imwrite('cut.jpg',img)

1111.jpg.jpeg

例子:选择橘子的部分并把他拷贝到原图像的其他区域。

img = cv2.imread("citrus-fruit-colorful-delicious-2146386.jpg")
#print(img.shape)
px = img[3000:4800,0:3600]
img[0:1800,0:3600]=px
cv2.imwrite('roi.jpg',img)
roi.jpg.jpeg

5.拆分图像通道

有时我们需要对 BGR 三个通道分别进行操作。这是你就需要把 BGR 拆分成单个通道。

例子:只保留绿色通道

img = cv2.imread("beautiful-branch-bright-2275453.jpg")
#b,g,r=cv2.split(img) # 不推荐使用,原因耗时
img[:,:,0] = 0
#img[:,:,1] = 0
img[:,:,2] = 0
cv2.imwrite('g.jpg',img)
g.jpg

6.为图像扩边(填充)

如果你想在图像周围创建一个边,就像相框一样,你可以使用 cv2.copyMakeBorder()函数。这经常在卷积运算或 0 填充时被用到。

copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]])

这个函数参数意义如下:

  • src:表示图像的numpy.ndarray对象

  • top,bottom,left,right :上下左右边界各填充多少

  • borderType:

    BORDER_REPLICATE:复制法,也就是复制最边缘像素。

    BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb

    BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba

    BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg

    BORDER_CONSTANT:常量法,常数值填充。

  • value:当为BORDER_CONSTANT时,需要填充颜色可以是0或255(黑白),也可以是(0,0,255)BGR

img = cv2.imread("beautiful-branch-bright-2275453.jpg")
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

top_size,bottom_size,left_size,right_size = (300,300,300,300)

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,0,255))# 这里(0,0,255)为RGB,为蓝色

plt.figure(figsize=(12,5),dpi=100)
plt.subplot(231), plt.imshow(img, 'gray'), plt.axis('off'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.axis('off'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.axis('off'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.axis('off'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.axis('off'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.axis('off'), plt.title('CONSTANT')

由于是使用 matplotlib 绘制,所以交换 R 和 B 的位置,OpenCV 中是按 BGR,matplotlib 中是按 RGB 排列,因此,使用cv2.cvtColor(img,cv2.COLOR_BGR2RGB)将BGR转换为RGB。

边界填充.png

参考资料:《数字图像处理》《OpenCV-Python 中文教程》

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

推荐阅读更多精彩内容