opencv学习笔记(七):图像的基础操作

opencv学习笔记(七):图像的基础操作

获取像素值

读取彩色图像的像素值

首先我们需要读入一幅图像,可以根据像素的行和列的坐标获取他的像素值。对 BGR 图像而言,返回值为 B,G,R 的值。

读取某点处的所有通道的值
import cv2
import numpy as np
#读取图片
img = cv2.imread('1.jpg',cv2.IMREAD_UNCHANGED)
#img(x,y)返回像素值
print('该点的像素值为:',img[200,200])

运行结果如下:

[Running] python -u "f:\Opencv\getpx.py"
该点的像素值为: [101  49  49]

[Done] exited with code=0 in 0.213 seconds
读取某点处某一通道的值

当读取的图像为img时,可以利用img[x,y][0]等访问其某一通道值,例如:
img[x,y][0]:返回的是(x,y)点B通道的值
img[x,y][1]:返回的是(x,y)点G通道的值
img[x,y][2]:返回的是(x,y)点R通道的值

import cv2
import numpy as np

img = cv2.imread('1.jpg',cv2.IMREAD_UNCHANGED)
print('该点的B通道值为:',img[200,200][0])
print('该点的G通道值为:',img[200,200][1])
print('该点的R通道值为:',img[200,200][2])

运行结果如下:

[Running] python -u "f:\Opencv\getpx.py"
该点的B通道值为: 101
该点的G通道值为: 49
该点的R通道值为: 49

[Done] exited with code=0 in 0.224 seconds

读取灰度图的像素值

对灰度图而言,返回的是某点灰度值的大小,即亮度

import cv2
import numpy as np

img = cv2.imread('1.jpg',cv2.IMREAD_GRAYSCALE)
print('该点的B通道值为:',img[200,200])

运行结果如下:

[Running] python -u "f:\Opencv\getpx.py"
该点的灰度值为: 55

[Done] exited with code=0 in 0.224 seconds

修改像素值

既然我们可以访问某点的像素值,那么同样我们也可对该点的像素值进行赋值
将一张600*600*3的黑色图片转化为白色图片:

import cv2
import numpy as np
$读取图片
img = cv2.imread('225.jpg',cv2.IMREAD_UNCHANGED)
#利用for循环,遍历图像上的每一个点
for i in range (0,599):
    for j in range (0,599):
        #直接赋值,(i,j)点的BGR像素值为(255,255,255)
        img[i,j] = [255,255,255]
cv2.imshow('img',img)
cv2.imwrite('write.jpg',img)
if cv2.waitKey(0) == ord('q'):
    cv2.destroyAllWindows()

运行结果如下:
在这里插入图片描述

那这样遍历赋值的方法执行效率有多高呢?我们不妨打印出这段代码的执行时间

import cv2
import time #导入python库
import numpy as np
start = time.time()
img = cv2.imread('225.jpg',cv2.IMREAD_UNCHANGED)
for i in range (0,599):
    for j in range (0,599):
        img[i,j] = [255,255,255]
cv2.imshow('img',img)
cv2.imwrite('white.jpg',img)
print (time.time() - start)#代码运行时间
if cv2.waitKey(0) == ord('q'):
    cv2.destroyAllWindows()

运行结果如下:

[Running] python -u "f:\Opencv\changepx.py"
0.26805973052978516

其实对于图像操作,还有一种矩阵运算的操作方式可以帮助我们提高效率,这里我们借助NumPy模块进行矩阵运算。
使用NumPy模块修改像素值的方法是使用itemset函数,它可以修改图像上某一点单个通道的值,用NumPy模块完成相同任务,打印其执行时间:

import cv2
import time
import numpy as np
start = time.time()
img = cv2.imread('225.jpg',cv2.IMREAD_UNCHANGED)
for i in range (0,599):
    for j in range (0,599):
        img.itemset((i,j,0),255)
        img.itemset((i,j,1),255)
        img.itemset((i,j,2),255)
cv2.imshow('img',img)
cv2.imwrite('white.jpg',img)
print (time.time() - start)
if cv2.waitKey(0) == ord('q'):
    cv2.destroyAllWindows()

运行结果如下:

[Running] python -u "f:\Opencv\changepx.py"
0.19304275512695312

显然使用NumPy模块效率更高
另一个实验,在白色图片的四个特征点上画出20*20的红色正方形

import cv2
import time
import numpy as np
img = cv2.imread('white.jpg',cv2.IMREAD_UNCHANGED)
(x,y,z) = img.shape
for i in range(-20,20):
    for j in range(-20,20):
        img.itemset((int(x/4)+i,int(y/4)+j,0),0)#第一个特征点,设置20*20区域内点的B通道为0
        img.itemset((int(x/4)+i,int(y/4)+j,1),0)#设置20*20区域内的G通道为0
for i in range(-20,20):
    for j in range(-20,20):
        img.itemset((int(x*3/4)+i,int(y/4)+j,0),0)#第二个特征点
        img.itemset((int(x*3/4)+i,int(y/4)+j,1),0)
for i in range(-20,20):
    for j in range(-20,20):
        img.itemset((int(x/4)+i,int(y*3/4)+j,0),0)#第三个特征点
        img.itemset((int(x/4)+i,int(y*3/4)+j,1),0)
for i in range(-20,20):
    for j in range(-20,20):
        img.itemset((int(x*3/4)+i,int(y*3/4)+j,0),0)#第四个特征点
        img.itemset((int(x*3/4)+i,int(y*3/4)+j,1),0)
cv2.imshow('img',img)
if cv2.waitKey(0) == ord('q'):
    cv2.destroyAllWindows()

运行结果如下:
在这里插入图片描述

拆分图像通道 cv2.spilt(),合并图像通道cv2.merge()

实现图像通道的拆分主要是调用NumPy模块中的np.spilt()函数,在此只展示如何拆分图像通道,关于NumPy模块的用法将单列为系列笔记

import cv2
import numpy as np
#读取图片
img = cv2.imread(('lena.png'),cv2.IMREAD_UNCHANGED)
#拆分图像通道 B G R
Bimg,Gimg,Rimg = cv2.split(img)
#创建与图片大小相当的零矩阵
zeros= np.zeros(img.shape[:2],np.uint8)
#cv2.merge合并通道,将单通道图像与零矩阵合并
cv2.imshow("DISPLAY BLUE COMPONENT",cv2.merge([Bimg,zeros,zeros]))  #显示(B,0,0)图像
cv2.imshow("DISPLAY GREEN COMPONENT",cv2.merge([zeros,Gimg,zeros]))  #显示(0,G,0)图像
cv2.imshow("DISPLAY RED COMPONENT",cv2.merge([zeros,zeros,Rimg]))  #显示(0,0,R)图像
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

图像扩边 cv2.copyMakeBorder()

函数原型:cv2.copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]]	)
参数说明:
src	        Source image.
top	
bottom	
left	
right	        Parameter specifying how many pixels in each direction from the source image rectangle to extrapolate. For example, top=1, bottom=1, left=1, right=1 mean that 1 pixel-wide border needs to be built.
borderType	Border type. See borderInterpolate for details.
value	        Border value if borderType==BORDER_CONSTANT .

src:源图像
top:上轮廓填充的像素点数目
bottom:下轮廓填充的像素点数目
left:左轮廓填充的像素点数目
right:右轮廓填充的像素点数目
borderType 添加轮廓的类型
value 如果选择的轮廓类型为BORDER_CONSTANT,则该值为图像的颜色

borderType参数说明:
在这里插入图片描述

下面通过程序观察不同扩边类型的效果:
程序中使用的原图像如下:
在这里插入图片描述

添加一种颜色的轮廓

import cv2
import numpy as np
img = cv2.imread('2.jpg',cv2.IMREAD_UNCHANGED)
img = cv2.copyMakeBorder(img,50,50,50,50,cv2.BORDER_CONSTANT,value = (255,255,255))
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果如下:原图像外多了一层白色轮廓
在这里插入图片描述

添加镜像轮廓(1)

import cv2
import numpy as np
img = cv2.imread('2.jpg',cv2.IMREAD_UNCHANGED)
img = cv2.copyMakeBorder(img,50,50,50,50,cv2.BORDER_REFLECT)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果如下:以原图像各边作为对称轴进行对称
在这里插入图片描述

添加镜像轮廓(2)

import cv2
import numpy as np
img = cv2.imread('2.jpg',cv2.IMREAD_UNCHANGED)
img = cv2.copyMakeBorder(img,50,50,50,50,cv2.BORDER_REFLECT_101)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果如下:
在这里插入图片描述

根据运行结果,肉眼观察两次镜像扩边效果相同,其实不然:
cv2.BORDER_REFLECT生成的是完全镜像,例如:若原图像上在一个方向上的像素点分布是abcdefgh,则其上下或左右两侧扩边后的图像为hgfedcba||abcdefgh
cv2.BORDER_REFLECT_101生成的是近似镜像,例如:若原图像上在一个方向上的像素点分布是abcdefgh,则其上下或左右两侧扩边后的图像为gfedcb||abcdefgh||gfedcb,显然这种扩边方式不会镜像最外侧像素点

图像扩边在扩大图像后进行图片过滤的过程中会时常用到,具有重要意义。

猜你喜欢

转载自blog.csdn.net/zxt510001/article/details/126844005
今日推荐