opencv-python学习之旅
opencv-python 操作
*注:在此笔记中只记录下各种函数的使用,规则
详细讲解见https://opencv.apachecn.org/#/docs/4.0.0/2.1-tutorial_py_image_display
创建,读取,显示,保存图像
创建图像
import numpy as np
img = np.zeros((512,512,3),np.uint8) # 创建一个图像 ,3 是指三个通道,可传入RGB
读取图像
cv2.imread(“本工作目录下的文件名”,-1或0或1) # -1:加载图像,包括alpha通道,0:灰色模式加载图像,1:默认正常模式加载
显示图像
cv.imshow('image', img) # imshow("窗口名字",要显示的图像)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey() 是一个键盘绑定函数,它的参数是以毫秒为单位的时间。该函数为任意键盘事件等待指定毫秒。如果你在这段时间内按下任意键,程序将继续。如果传的是 0,它会一直等待键盘按下。它也可以设置检测特定的击键,例如,按下键 a 等,我们将在下面讨论。
Note
除了绑定键盘事件,该函数还会处理许多其他 GUI 事件,因此你必须用它来实际显示图像。
cv.destroyAllWindows() 简单的销毁我们创建的所有窗口。如果你想销毁任意指定窗口,应该使用函数 cv.destroyWindow() 参数是确切的窗口名。
eg.下面的程序以灰度模式读取图像,显示图像,如果你按下 's‘ 会保存和退出图像,或者按下 ESC 退出不保存。
import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg',0)
cv.imshow('image',img)
k = cv.waitKey(0)
if k == 27: # ESC 退出
cv.destroyAllWindows()
elif k == ord('s'): # 's' 保存退出
cv.imwrite('messigray.png',img)
cv.destroyAllWindows()
Note
有一种特殊情况,你可以先创建一个窗口然后加载图像到该窗口。在这种情况下,你能指定窗口是否可调整大小。它是由这个函数完成的 cv.namedWindow()。默认情况下,flag 是 cv.WINDOW_AUTOSIZE。但如果你指定了 flag 为 cv.WINDOW_NORMAL,你能调整窗口大小。当图像尺寸太大,在窗口中添加跟踪条是很有用的。
看下面的代码:
cv.namedWindow('image', cv.WINDOW_NORMAL)
cv.imshow('image',img)
cv.waitKey(0)
cv.destroyAllWindows()
保存图像
保存图像,用这个函数 cv.imwrite()。
第一个参数是文件名,第二个参数是你要保存的图像。
cv.imwrite('messigray.png',img)
将该图像用 PNG 格式保存在工作目录。
使用 Matplotlib
Matplotlib 是一个 Python 的绘图库,提供了丰富多样的绘图函数。你将在接下来的文章中看到它们。在这里,你将学习如何使用 Matplotlib 来显示图像。你还能用 Matplotlib 缩放图像,保存图像等。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('messi5.jpg',0)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic') # 让图像以灰色形式展示
# 或者选择 plt.imshow(img[:,:,::-1]) #这一步操作,保证和原图像显示的色彩一致
plt.xticks([]), plt.yticks([]) # 隐藏 X 和 Y 轴的刻度值 去掉则会显示刻度
plt.show()
色彩模式与cv2不一样(BGR),因此显示出来的颜色不对,需要改一下
plt.imshow(img[:,:,::-1]) #这一步操作,保证和原图像显示的色彩一致
plt.show()
图像的绘制功能
画线
去画一条线,你需要传递线条的开始和结束的坐标。我们将创建一个黑色图像,并在坐上角到右下角画一条蓝色的线
import numpy as np
import cv2 as cv
# 创建一个黑色的图像
img = np.zeros((512,512,3), np.uint8)
# 画一条 5px 宽的蓝色对角线
cv.line(img,(0,0),(511,511),(255,0,0),5)
cv2.line(图像,(起始坐标),(终点坐标),(颜色),宽度)
画圆
画一个圆,你需要它的圆心和半径。我们将在上面绘制的矩形上画一个内圆。
cv.circle(img,(447,63), 63, (0,0,255), -1)
cv.circle(图像,(圆心坐标x,y),半径,(颜色),加载方式)
画椭圆
画一个椭圆,你需要传好几个参数。一个参数是圆心位置 (x,y)。下个参数是轴的长度 (长轴长度,短轴长度)。角度是椭圆在你逆时针方向的旋转角度。startAngle 和 endAngle 表示从长轴顺时针方向测量的椭圆弧的起点和终点。如整圆就传 0 和 360。更多细节请看 cv.ellipse() 的文档。下面是在这个图像中间画的一个半椭圆例子。
cv.ellipse(img,(256,256),(100,50),0,0,180,(0,255,255),-1)
cv.ellipse(图像,(圆心坐标),(长轴,短轴),起时角度,起点,终点,颜色,加载方式
画矩形
cv.rectangle(img,左上角坐标,右下角坐标,颜色,线条厚度)
画多边形
画多边形,首先你需要顶点的做坐标。将这些点组成一个形状为 ROWSx1x2 的数组,ROWS 是顶点数,它应该是 int32 类型。这里我们绘制一个顶点是黄色的小多边形。
pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
pts = pts.reshape((-1,1,2))
cv.polylines(img,[pts],True,(0,255,255))
Note
- 如果地三个是 False,你将获得所有点的折线,而不是一个闭合形状。
- cv.polylines() 能画很多线条。只需创建你想绘制所有线条的列表,然后将其传给这个函数。所有线条都将单独绘制。绘制一组线条比调用 cv.line() 好很多,快很多。
绘图添加文字
cv.putText(img,输入内容,文本的放置位置,字体,字体大小,颜色,线条宽度,cv.LINE__AA)
访问并修改像素点
通过行列坐标来进行访问及修改
黄色为绿色和红色的混合。所以,该图像的所有像素值都应为R=255,G=255,B=0。
>>> import numpy as np
>>> import CV2
>>> img = CV2.imread("img/yellow.jpg")
>>> h,w,c = img.shape
#图像大小为128*128*3
>>> print(h,w,c)
128 128 3
px = img[100,100] # 获取某个点的像素值
从上面的代码中可以看到,您可以通过行和列坐标访问像素值。注意,对于常见的RGB 图像,OpenCV的imread函数返回的是一个蓝色(Blue)值、绿色(Green)值、红色(Red)值的数组,维度大小为3。而对于灰度图像,仅返回相应的灰度值。
>>> img[100,100]
#OpenCV的读取顺序为B,G,R,由于图像所有像素为黄色,因此,G=255,R=255
array([ 0, 255, 255], dtype=uint8)
# 仅访问蓝色通道的像素
>>> blue = img[100,100,0]
>>> print(blue)
0
你也可以使用同样的方法来修改像素值。
>>> img[100,100] = [255,255,255]
>>> print(img[100,100])
[255 255 255]
访问属性
图像大小
img.shape # 变量.shape
(256,256,3)
img.shape[:2] 取彩色图片的长、宽。
- 使用彩色模式传参时
cols,rows = img.shape[:2]
# 或者
cols,rows,x = img.shape
使用灰色模式
cols ,rows = img.shape
如果img.shape[:3] 则取彩色图片的长、宽、通道。
关于img.shape[0]、[1]、[2]
img.shape[0]:图像的垂直尺寸(高度)
img.shape[1]:图像的水平尺寸(宽度)
img.shape[2]:图像的通道数
数据类型
img.dtype
dtype('uint8')
像素点数量
img.size
196608
图像的裁剪、拼接、翻转、缩放等 [(https://blog.csdn.net/zh_jessica/article/details/77946346)]
缩放:
一、图像缩放
图像缩放主要使用resize函数
result = cv2.resize(src, dsize[, result[. fx[, fy[, interpolation]]]]) 记得要用新变量来接收
其中src表示原始图像,dsize表示缩放大小,fx和fy也可以表示缩放大小倍数,他们两个(dsize或fx\fy)设置一个即可实现图像缩放
参数说明:
src - 原图
dst - 目标图像。当参数dsize不为0时,dst的大小为size;否则,它的大小需要根据src的大小,参数fx和fy决定。dst的类型(type)和src图像相同
dsize - 目标图像大小。当dsize为0时,它可以通过以下公式计算得出:
所以,参数dsize和参数(fx, fy)不能够同时为0
fx - 水平轴上的比例因子。当它为0时,计算公式如下:
fy - 垂直轴上的比例因子。当它为0时,计算公式如下:
interpolation - 插值方法。共有5种:
INTER_NEAREST - 最近邻插值法
INTER_LINEAR - 双线性插值法(默认)
INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)。对于图像抽取也叫缩小图像(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。
INTER_CUBIC - 基于4x4像素邻域的3次插值法
INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值
缩小图像 用INTER_AREA更好,放大图像用 INTER_CUBIC更好;
————————————————
代码如下:
import cv2
#读取图片
image = cv2.imread("E:/pythonProject/xin.jpeg")
#图片缩放
image1 = cv2.resize(image, (200,200))
#图片显示
cv2.imshow("resize", image1)
cv2.imshow("image", image)
#等待窗口
cv2.waitKey(0)
旋转
opencv中对图像的旋转主要是先通过getRotationMatrix2D函数得到图像的旋转矩阵,然后再通过仿射变换函数warpAffine得到旋转后的图像。
函数说明:
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 时的填充值
代码示范:
img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape
#90度旋转
M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))
平移
- 平移translate
平移通过自定义平移矩阵以及函数warpAffine实现:
代码示范:
img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape
# 平移矩阵M:[[1,0,x],[0,1,y]]
M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))
反转
- 翻转flip
翻转通过函数flip实现:
函数说明:
cv2.flip(src, flipCode[, dst]) → dst
1
参数说明:
src – 输入的图像
dst – 输出的图像
flipCode – 翻转模式,flipCode==0垂直翻转(沿X轴翻转),flipCode>0水平翻转(沿Y轴翻转),flipCode<0水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)
代码示范:
# 水平翻转
flip_horiz_img = cv2.flip(pad_img, 1)
# 垂直翻转
flip_verti_img = cv2.flip(pad_img, 0)
# 水平垂直翻转
flip_horandver_img = cv2.flip(pad_img, -1)
拼接
单个图像多次拼接
import cv2
img =cv2.imread(file_path[i])
img=cv2.hconcat([img,img,img])#水平拼接
img=cv2.vconcat([img,img,img])#垂直拼接
多个相似特征图像拼接(开摆!)
import cv2
import numpy as np
def stitch(image):
# 图像拼接
# stitcher = cv2.createStitcher(False) # OpenCV 3.X.X.X使用该方法
stitcher = cv2.Stitcher_create(cv2.Stitcher_PANORAMA) # OpenCV 4.X.X.X使用该方法,cv2.Stitcher_create()也可以
status, pano = stitcher.stitch(image)
# 黑边处理
if status == cv2.Stitcher_OK:
# 全景图轮廓提取
stitched = cv2.copyMakeBorder(pano, 10, 10, 10, 10, cv2.BORDER_CONSTANT, (0, 0, 0))
gray = cv2.cvtColor(stitched, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1]
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
# 轮廓最小正矩形
mask = np.zeros(thresh.shape, dtype="uint8")
(x, y, w, h) = cv2.boundingRect(cnts[0]) # 取出list中的轮廓二值图,类型为numpy.ndarray
cv2.rectangle(mask, (x, y), (x + w, y + h), 255, -1)
# 腐蚀处理,直到minRect的像素值都为0
minRect = mask.copy()
sub = mask.copy()
while cv2.countNonZero(sub) > 0:
minRect = cv2.erode(minRect, None)
sub = cv2.subtract(minRect, thresh)
# 提取minRect轮廓并裁剪
cnts = cv2.findContours(minRect, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
(x, y, w, h) = cv2.boundingRect(cnts[0])
stitched = stitched[y:y + h, x:x + w]
cv2.imshow('stitched', stitched)
cv2.imwrite('stitched.jpg', stitched)
cv2.waitKey(0)
cv2.destroyAllWindows()
else:
print('图像匹配的特征点不足')
if __name__ == "__main__":
image1 = cv2.imread('data/space1.jpg')
image2 = cv2.imread('data/space2.jpg')
image3 = cv2.imread('data/space3.jpg')
image = image1, image2, image3
stitch(image)
(18条消息) OpenCV-Python 图像全景拼接stitch及黑边处理_Klein-的博客-CSDN博客_stitcher_create
opencv-python学习之旅的更多相关文章
- 180分钟的python学习之旅
最近在很多地方都可以看到Python的身影,尤其在人工智能等科学领域,其丰富的科学计算等方面类库无比强大.很多身边的哥们也提到Python非常的简洁方便,比如用Django搭建一个见得网站只需要半天时 ...
- python学习之旅
python学习分类 python基础 +- day01——python初始.变量.常量.注释.基础数据类型.输入.if day02——while.字符串格式化.运算符.编码初识 day03—— ...
- python学习之旅:array 转 list
最近学习python,记录学习的点滴. >>> import numpy as np >>> a = np.array([[1,2],[3,4]]) >> ...
- Python学习之旅(三十八)
Python基础知识(37):访问数据库(Ⅱ) 二.MySQL MySQL是Web世界中使用最广泛的数据库服务器.SQLite的特点是轻量级.可嵌入,但不能承受高并发访问,适合桌面和移动应用.而MyS ...
- Python学习之旅(三十六)
Python基础知识(35):电子邮件(Ⅱ) 收取邮件就是编写一个MUA作为客户端,从MDA把邮件获取到用户的电脑或者手机上 收取邮件最常用的协议是POP协议,目前版本号是3,俗称POP3 Pytho ...
- Python学习之旅(三十三)
Python基础知识(32):网络编程(Ⅰ) 网络通信是两台计算机上的两个进程之间的通信,而网络编程就是如何在程序中实现两台计算机的通信 P协议负责把数据从一台计算机通过网络发送到另一台计算机 TCP ...
- Python学习之旅(三十二)
Python基础知识(31):图形界面(Ⅱ) Python内置了turtle库,可以在计算机上绘图 运动控制: 1.画笔定位到坐标(x,y):turtle.goto(x,y) 2.向正方向运动 dis ...
- Python学习之旅(三十)
Python基础知识(29):virtualenv virtualenv:用来为一个应用创建一套隔离的Python运行环境 比如,现有两个Python项目,一个是Python2.7的一个是Python ...
- Python学习之旅:使用virtualenv创建Python环境及PyQT5环境配置
一.写在前面 从学 Python 的第一天起,我就知道了使用 pip 命令来安装包,从学习爬虫到学习 Web 开发,安装的库越来越多,从 requests 到 lxml,从 Django 到 Flas ...
- python学习之旅1-2(基础知识)
三,python基础初识. 1.运行python代码. 在d盘下创建一个t1.py文件内容是: print('hello world') 打开windows命令行输入cmd,确定后 写入代码pytho ...
随机推荐
- 关于docker-环境部署及拉取镜像创建容器的过程记录
背景:因安全部门要求对特定几台应用主机的进行漏洞及脆弱性扫描,使用的工具需要基于docker环境,即他们提供镜像,让我们创建成容器,于是将整个环境安装及创建docker容器的过程记录于此 1.还是先得 ...
- 云原生时代的DevOps平台设计之道
开发人员与运维人员是 IT 领域很重要的两大人群,他们都会参与到各种业务系统的建设过程中去.DevOps 是近年间火爆起来的一种新理念,这种理念被很多人错误的解读为"由开发人员(Dev)学习 ...
- <jsp:useBean>动作的使用
jsp:useBean动作的使用 jsp:useBean动作用于在指定的范围内寻找指定名称的JavaBean对象,如果找到,则返回该对象的引用可以操作里边的属性.如果没有找到则重新实例化一个对象.并且 ...
- 【ps下载与安装】Adobe Photoshop 2022 for Mac v23.5 中文永久版下载 Ps图像编辑软件
Adobe Photoshop 2022 mac破解版,是一款Ps图像编辑软件,同时支持M1/M2芯片和Intel芯片安装,此主要的更新包括多个新增和改进的功能,例如改进的对象选择工具,其悬停功能可预 ...
- AI人脸识别+换脸
视频换脸可参考 https://github.com/iperov/DeepFaceLab import dlib.dlib as dlib import numpy import sys impor ...
- 制作一个windows垃圾清理小程序
制作一个windows垃圾清理小程序: 把下列代码保存为.bat文件(如垃圾清理.bat) 双击它就能很快地清理垃圾文件,大约一分钟不到. 就是下面的文字(这行不用复制)=============== ...
- 某 .NET RabbitMQ SDK 有采集行为,你怎么看?
一:背景 1.讲故事 前几天有位朋友在微信上找到我,说他的一个程序上了生产之后,被运维监控定位到这个程序会向一个网址为: http://m.365ey.net 上不定期打数据,而且还是加密的格式,要他 ...
- Cookie、Session、Token与JWT(跨域认证)
之前看到群里有人问JWT相关的内容,只记得是token的一种,去补习了一下,和很久之前发的认证方式总结的笔记放在一起发出来吧. Cookie.Session.Token与JWT(跨域认证) 什么是Co ...
- mybatis-核心配置文件讲解
核心配置文件详解 核心配置文件中的标签必须按照固定的顺序(有的标签可以不写,但顺序一定不能乱): properties.settings.typeAliases.typeHandlers.object ...
- 论文笔记 - An Explanation of In-context Learning as Implicit Bayesian Inference
这位更是重量级.这篇论文对于概率论学的一塌糊涂的我简直是灾难. 由于 prompt 的分布与预训练的分布不匹配(预训练的语料是自然语言,而 prompt 是由人为挑选的几个样本拼接而成,是不自然的自然 ...