OpenCV常用操作
原创:杨其泓
1 OpenCV入门基础
1.1 OpenCV简介
OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。OpenCV-Python是OpenCV的Python API,集成了Python语言和C++语言的最优特征,致力于支持Python解决计算机视觉问题。
1.2 Python安装OpenCV
在Python中安装OpenCV十分便捷,可以直接使用:pip install opencv-python
或conda insatll opencv-python
即可。
注:默认安装最新版,如有特定版本需求,可使用pip install opencv-python==4.1.2
。
在成功安装OpenCV后,可以在Python编译器中键入如下内容,查看是否安装成功:
import cv2
print(cv2.__version__)
1.3 图片的读取、显示与保存
- 图像读取
使用OpenCV读取图片文件,可以使用函数cv2.imread(filepath, flags)
,例如:
image=cv2.imread('test.jpg')
该函数共接收两个输入,即要读入图片的完整路径和读入图片的方式,常用方式包括以下三种
- cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道
- cv2.IMREAD_GRAYSCALE:读入灰度图片
- cv2.IMREAD_UNCHANGED:顾名思义,读入完整图片,包括alpha通道
OpenCV读取图片后返回的是一个numpy数组,对于彩色图像,数组为三维数组,其形状(shape)为(图像高,图像宽,3),其中3代表图片的RGB三个通道,由于OpenCV在存储彩色图像时,默认通道顺序为BGR,在进行图像处理时要注意不要使用错误的通道顺序。
- 图像显示
使用OpenCV显示图片文件,可以使用函数cv2.imshow(wname, img)
,例如:
cv2.imshow('Test_image', image)
在多数时候,我们会将上述API搭配cv2.waitKey()
和cv2.destroyAllWindows()
使用,waitKey顾名思义,就是等待键盘键入,而destroyAllWindows就是关闭所有已经显示的窗口,搭配这两个API后即可实现:显示一张图片,并在键盘键入任意值后关闭图片的效果。
下面就是使用OpenCV读入图片并展示的样例代码:
import cv2
image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
image_gray = cv2.imread('KKB.jpeg', cv2.IMREAD_GRAYSCALE)
cv2.imshow('BGR', image_BGR)
cv2.imshow('gray', image_gray)
cv2.waitKey()
cv2.destroyAllWindows()
输出效果如下:
- 图像保存
使用OpenCV显示图片文件,可以使用函数cv2.imwrite(file, img, num)
,例如:
cv2.imwrite('testimage.jpeg', image_BGR)
# cv2.imwrite('testimage.jpeg', image_BGR, [int(cv2.IMWRITE_JPEG_QUALITY), 95])
# cv2.imwrite('testimage.jpeg', image_BGR, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])
这个API有三个参数:第一个参数是要保存的文件路径,第二个参数是要保存的图像。第三个参数是可选参数,它针对特定的格式:对于JPEG,其表示的是图像的质量,用0 - 100的整数表示,默认95;对于png ,第三个参数表示的是压缩级别,默认为3。
2 图像处理基础
2.1 像素处理
- 访问像素
在OpenCV中,我们可以直接以索引的方式访问图像的像素。例如我们访问刚才读取的图片(200, 200)坐标位置(左上角为坐标系原点)的像素可是使用:
import cv2
image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
print(image_BGR[200,200])
>>> [246 218 177]
可见,在(200, 200)坐标位置所对应的三通道像素值分别为B:246,G:218,R:177。
- 修改像素
图像像素值的修改也十分简单,下面我们将原始图片中的一部分区域修改为红色(0, 0, 255):
import cv2
image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
image_BGR[100:200, 100:200] = [0,0,255]
cv2.imshow('BGR', image_BGR)
cv2.waitKey()
cv2.destroyAllWindows()
所得到的结果为:
2.2 图像属性
- 图像形状
图像的形状可以通过image.shape
获得,例如:
import cv2
image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
print(image_BGR.shape)
>>> (684, 1067, 3)
可以看到,刚才我们打开的那张图片的高是684像素,宽是1067像素,通道数为3。
- 像素数目
图像的像素数目可以理解为图像中的像素值总量,也就是行*列*通道,可以通过image.size
获得,例如:
import cv2
image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
print(image_BGR.size)
>>> 2189484
我们来验证一下,刚才我们打开的那张图片的高是684像素,宽是1067像素,通道数为3,那他的像素数量应为这三者的乘积,即为684∗1067∗3=2189484684*1067*3=2189484684∗1067∗3=2189484,与上述代码中计算所得相同。
- 图像类型
图像的类型可以通过image.dtype
获得,例如:
import cv2
image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
print(image_BGR.dtype)
>>> uint8
由此可见,这张图片的属性是uint8。
3 图像运算
3.1 图像加法
我们知道,以uint8形式存储的图片的取值范围是[0, 255],即0代表纯黑,1代表纯白,0~1之间的值则表示由深到浅的灰色。那么在对图像做加法的时候,就会产生一个问题:像素值为100的图片+像素值为100的图片,可以获得像素值为200的图片,但如果是150+150,两张图片相加之后的像素值超出255的范围怎么办?在这时候,有两种解决方案。
- 取模运算
一般来说我们可以直接使用+进行取模运算,即image_c = image_a + image_b
。取模运算顾名思义,就是对运算结果取模,此时两个像素值的相加大家可以理解为:
def image_add(pixel_a, pixel_b):if pixel_a + pixel_b <= 255:return pixel_a + pixel_bif pixel_a + pixel_b > 255:return (pixel_a + pixel_b) % 255
也就是在不超出255范围时:100+100=200100+100=200100+100=200,在超出255范围时:150+150=(150+150)%255=45150+150=(150+150)\%255=45150+150=(150+150)%255=45。
- 饱和运算
饱和运算就更好理解了,两个像素值相加,如果超出255的限制,则直接取255。使用cv2.add(a, b)
即可进行饱和运算。
取模运算和饱和运算的代码及效果图如下:
import cv2
image_a = cv2.imread('dog.jpeg', cv2.IMREAD_GRAYSCALE)
image_b= cv2.imread('cat.jpeg', cv2.IMREAD_GRAYSCALE)image_c = image_a + image_b
image_d = cv2.add(image_a, image_b)cv2.imshow('image_a', image_a)
cv2.imshow('image_b', image_b)
cv2.imshow('image_c', image_c)
cv2.imshow('image_d', image_d)
cv2.waitKey()
cv2.destroyAllWindows()
3.2 图像融合
图像融合其实也是图像加法的一种, 图像融合为两张图像赋予了不同的权重,从而使图像具有混合或透明的感觉。在OpenCV中,可以使用cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])
来进行图像融合,此函数会依据下列表达式来进行运算dst=src1∗alpha+src2∗beta+gammadst = src1 * alpha + src2 * beta + gammadst=src1∗alpha+src2∗beta+gamma,也就是对图片1和图片2分别乘一个系数后相加,并添加gamma作为偏置。图像融合的代码及效果图如下:
import cv2
image_a = cv2.imread('dog.jpeg', cv2.IMREAD_GRAYSCALE)
image_b= cv2.imread('cat.jpeg', cv2.IMREAD_GRAYSCALE)image_c = cv2.addWeighted(image_a, 0.5, image_b, 0.5, 0)cv2.imshow('image_a', image_a)
cv2.imshow('image_b', image_b)
cv2.imshow('image_c', image_c)
cv2.waitKey()
cv2.destroyAllWindows()
4 图像几何变换
4.1 图像缩放
图像缩放其实就是改变图像的大小、形状,可以用下列API来实现:
Image = cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
这个API的参数较多,但其实很好理解,下面就是API的参数解释:
- Image:输出图像
- src:输入图像
- dsize:输出图像的尺寸
- fx:横坐标缩放比例
- fy:纵坐标缩放比例
- interpolation:缩放方式
在这些参数中,输入、输出图像都很好理解,输出图像的尺寸dsize是(宽,高),fxfy一般可直接使用0-1的缩放比例,值得注意的一点是,在给定dsize时,就不用另外输入缩放比例了,而想使用缩放比例时,disze应输入None(不可不输入)。缩放方式一般不填,直接使用默认值即可,其他缩放方式如下:
- INTER_NEAREST 最近邻插值
- INTER_LINEAR 双线性插值(默认设置)
- INTER_AREA 使用像素区域关系进行重采样。 它可能是图像抽取的首选方法,因为它会产生无云纹理的结果。 但是当图像缩放时,它类似于INTER_NEAREST方法。
- INTER_CUBIC 4x4像素邻域的双三次插值
- INTER_LANCZOS4 8x8像素邻域的Lanczos插值
图像缩放的代码如下:
import cv2
image = cv2.imread('dog.jpeg', cv2.IMREAD_GRAYSCALE)
print(image.shape)
>>> (224, 225)
image = cv2.resize(image,(175,175))
print(image.shape)
>>> (175, 175)
4.2 图像翻转
图像的翻转可以使用cv2.flip(src, flipCode)
实现,在这个API中需要输入一个翻转的模式flipCode:
- flipCode为0代表垂直翻转(沿X轴翻转);
- flipCode大于0代表水平翻转(沿Y轴翻转);
- flipCode小于0代表水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)
图片翻转的代码及样例图如下:
import cv2
image= cv2.imread('cat.jpeg', cv2.IMREAD_GRAYSCALE)
image = cv2.resize(image,(300,300))
image_a = cv2.flip(image, -1)
image_b = cv2.flip(image, 0)
image_c = cv2.flip(image, 1)cv2.imshow('image', image)
cv2.imshow('image_a', image_a)
cv2.imshow('image_b', image_b)
cv2.imshow('image_c', image_c)
cv2.waitKey()
cv2.destroyAllWindows()
4.3 图像旋转
图像的旋转比翻转要复杂一些,图像旋转过程中,要先求得旋转矩阵,而后在通过仿射变化函数对图像进行旋转。
cv2.getRotationMatrix2D(center, angle, scale) # 旋转矩阵
cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst # 仿射变化
参数说明:
getRotationMatrix2D:
- center–表示旋转的中心点
- angle–表示旋转的角度degrees
- scale–图像缩放因子
warpAffine:
- src – 输入的图像
- M – 2 X 3 的变换矩阵.
- dsize – 输出的图像的size大小
- dst – 输出的图像
- flags – 输出图像的插值方法
- borderMode – 图像边界的处理方式
- borderValue – 当图像边界处理方式为BORDER_CONSTANT 时的填充值
图片旋转的代码及样例图如下(顺时针转90度):
import cv2
image = cv2.imread('dog.jpeg', cv2.IMREAD_GRAYSCALE)
h, w = image.shapeM = cv2.getRotationMatrix2D((w//2,h//2),-90,1.0)
dst = cv2.warpAffine(image,M,(w,h))cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
5 图像平滑处理
5.1 均值滤波
均值滤波是最简单的滤波器,它取卷积核区域下所有像素的平均值并替换中心元素,均值滤波的代码及样例图如下:
import cv2
image = cv2.imread('dog.jpeg')
img_mean = cv2.blur(image, (5,5)) # 原图,核心大小
cv2.imshow('image', image)
cv2.imshow('img_mean', img_mean)
cv2.waitKey()
cv2.destroyAllWindows()
5.2 中值滤波
中值滤波器是一种非线性滤波器,它的基本原理是:选择待处理像素的一个邻域中各像素值的中值来代替待处理的像素。它能使某像素的灰度值与周围领域内的像素比较接近,从而消除一些孤立的噪声点,所以中值滤波器能够很好的消除椒盐噪声。中值滤波的代码及样例图如下:
import cv2
image = cv2.imread('dog.jpeg')
img_median = cv2.medianBlur(image, 5) # 原图,核心大小
cv2.imshow('image', image)
cv2.imshow('img_median', img_median)
cv2.waitKey()
cv2.destroyAllWindows()
5.3 高斯滤波
高斯滤波也是一种常见的滤波器,与中值滤波不同的是,它是使用高斯核心来计算的:
h(x,y)=e−(x2+y2)2σ2h(x,y)=e^{\frac{-(x^2+y^2)}{2\sigma^2}} h(x,y)=e2σ2−(x2+y2)
其中(x,y)(x,y)(x,y)是图像中的点的坐标, σ\sigmaσ为标准差。x和y都是代表以核中心点为坐标原点的坐标值,对于而言 σ\sigmaσ,当 σ\sigmaσ比较小的时候,生成的高斯模板中心的系数比较大,而周围的系数比较小,这样对图像的平滑效果不明显。当比较大时 σ\sigmaσ,生成的模板的各个系数相差就不是很大,比较类似于均值模板,对图像的平滑效果比较明显。高斯滤波的代码及样例图如下:
import cv2
image = cv2.imread('dog.jpeg')
img_Guassian = cv2.GaussianBlur(image,(5,5),0) # 原图,核心大小,sigma
cv2.imshow('image', image)
cv2.imshow('img_Guassian', img_Guassian)
cv2.waitKey()
cv2.destroyAllWindows()
5.4 双边滤波
双边滤波是一种非线性滤波方法,是结合了图像的邻近度和像素值相似度的一种折中,在滤除噪声的同时可以保留原图的边缘信息。整个双边滤波是由两个函数构成:一个函数是由空间距离决定的滤波器系数,另外一个诗由像素差值决定的滤波器系数,双边滤波具体计算过程在这里就不赘述了。双边滤波的代码及样例图如下:
import cv2
image = cv2.imread('dog.jpeg')
img_bilater = cv2.bilateralFilter(image,9,75,75)
cv2.imshow('image', image)
cv2.imshow('img_bilater', img_bilater)
cv2.waitKey()
cv2.destroyAllWindows()
OpenCV常用操作相关推荐
- opencv 常用操作 c++
图像水平垂直方向拼接: cv::vconcat(B,C,A); // 等同于A=[B ;C] cv::hconcat(B,C,A); // 等同于A=[B C] 初始化Mat: cv::Mat edg ...
- opencv 图像操作,常用 OpenCV 内置函数
OpenCV 如何对图像的像素进行操作 对图像的像素进行操作,我们可以实现空间增强,反色,大部分图像特效系列都是基于像素操作等目的.先来看一下内存空间中图像矩阵,也就是Mat的矩阵数值部分是怎么存储的 ...
- OpenCV形态学操作
OpenCV形态学操作 本文转载自:http://blog.csdn.net/byxdaz/article/details/5775717 一.图像腐蚀 膨胀 细化的基本原理 1.图像细化的基本原 ...
- Eigen::常用操作[转]
Opencv::Mat 与 Eigen互转 Opencv::Mat转Eigen #include <Eigen/Dense> #include <iostream> #incl ...
- 【无标题】c++ MFC图像处理CImage类常用操作代码
原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/9598974.html 我看了一下发现关于c++下的CImage图像处理类 的图像处理相关的介绍 ...
- Opencv的使用小教程2——Opencv常用图像处理函数汇总
Opencv的使用小教程2--Opencv常用图像处理函数汇总 1.blur 2.GaussianBlur 3.medianBlur 4.bilateralFilter 5.腐蚀和膨胀 6.morph ...
- TensorFlow常用操作:代码示例
1,定义矩阵代码示例: import tensorflow as tftf.zeros([3,4]) #定义3行4列元素均为0的矩阵tensor=tf.constant([1,2,3,4])#定义一维 ...
- Ubuntu 常用操作
Ubuntu常用操作 外观操作 修改应用icon图标 终端美化 内存管理 内存查询 分区管理 日志清理 操作执行 自动执行多条命令 外观操作 修改应用icon图标 在/usr/share/applic ...
- IOS沙盒Files目录说明和常用操作
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launc ...
最新文章
- ASP.NET页面事件:顺序与回传详解
- C++中public protected private的区别
- 判断CPU大小端模式
- 1192 约瑟夫问题(1)
- 八皇后问题 (信息学奥赛一本通-T1213)
- 地图的文字注记的制作和优化
- 在Hisi3531环境中为wm8978芯片添加音量调节功能及测试
- 【太经典】如果有人问你数据库的原理,叫他看这篇文章
- 深入解析棋牌湖南放炮罚,跑胡子手游源码(java版)
- Could not enlist in transaction on entering meta-aware object!”
- 转:苹果CEO库克:伟大的想法来自不断拒绝接受现状
- 杭电ACM 2014:青年歌手大奖赛_评委会打分
- 全面解析ThreadLocal
- 投稿Springer旗下Natural Hazard的时间记载
- 2022渗透测试-面试题目大全
- MMSC BAPI/自动扩充库位
- GB28181/RTSP/Onvif/HikSDK/Ehome协议视频共享平台EasyCVR人脸识别系统助力打造智慧安检系统
- c#调用VLC播放视频,rtsp流
- HTML+CSS大作业:基于HMTL校园学校网页设计题材【我的学校网站】
- microblaze c语言,MicroBlaze
热门文章
- 外骨骼之人体行走的研究
- 公众号1200篇文章分类和索引
- 2018诺贝尔经济学奖得主,一名62岁的Python教徒
- A*算法求解N数码问题(AI实验一)
- unity编辑器上不穿模,真机Android上会穿模问题定位和解决
- 【SHARE分享】---GitChat程序猿的必备补给站
- 利用定时器 1和定时器0控制led1和led2分别 2hz和0.5hz闪烁
- 液体采样泵WKA1000升级品WKY1000
- 《EMBEDDING AND BEAMFORMING: ALL-NEURAL CAUSAL BEAMFORMER FORMULTICHANNEL SPEECH ENHANCEMENT》论文阅读
- linux配置网络(超级详细)