python opencv 图像切割_【OpenCV+Python】图像的基本操作与算术运算
图像的基本操作
在上个教程中,我们介绍了使用鼠标画笔的功能。本次教程,我们将要谈及OpenCV图像处理的基本操作。
本次教程的所有操作基本上都和Numpy相关,而不是与OpenCV相关。要使用OpenCV编写更好的优化代码,需要Numpy的丰富知识。
1.查看和修改像素值
我们要想查看一幅图像中某一个像素点的像素值,首先需要进行定位,将其坐标标定,我们先来看一个彩色图像(仍然是我们的猫咪,本次教程它是我们的主角):
现在我想查看某一个坐标的像素值,我们在pycharm中输入代码:
import cv2import numpy as npimg = cv2.imread("cat.jpg")#获取像素值px = img[200,200]print(px)
代码为查看图像坐标(200,200)处的像素值,我们来看结果:
在之前的教程中我们谈到,OpenCV对于图像的读取并非是RGB通道,而是BGR通道,那么程序输出的[178,189,186]则分别对应于BGR的像素,我们可以进行验证:
import cv2import numpy as npimg = cv2.imread("cat.jpg")#获取像素值px = img[200,200]B = img[200,200,0]G = img[200,200,1]R = img[200,200,2]print(px,B,G,R)
现在我们假设,如果图像并非彩色,而是黑白的灰度图像,那么将会怎么输出?先进行实验:
我们仍然用刚刚的代码进行实验(前提是图像已经灰度化处理,这在后面会讲到),效果:
可以看到,BGR的像素一致,我们得出一个结论:对于灰度图像,其输出的像素值本质上为它的亮度强度值,值的范围为0-255之间,当为0时,则全部为黑色,相反则为白色。
接下来我们来修改像素值,将指定坐标的像素值用一个数组进行赋值:
import cv2import numpy as npimg = cv2.imread("cat1.jpg")#获取像素值px = img[200,200]print(px)img[200,200] = [225,225,225]print(img[200,200])
查看输出:
可以看到,初始像素值跟修改之后的像素值。
一般来说,数组通常选择的是某一片区域,比如头几行或者最后几列。而对于某个像素点的访问,Numpy数组方法,array.item() 和array.itemset()有着更好的作用。但是它返回的是一个标量。所以如果我们想访问所有的B,G,R值,就需要分开调用array.item(),我们来看代码(仍然以坐标200,200为例):
import cv2import numpy as npimg = cv2.imread("cat.jpg")#获取像素值px = img[200,200]print(px)print(img.item(200,200,0))
我们用item输出像素的B值,也就是蓝色像素的数值:
实验可以看到,跟之前的效果是一样的。
对于指定坐标的赋值,我们使用itemset函数可以精确到某个像素,比如现在我只对蓝色像素的数值进行改变:
import cv2import numpy as npimg = cv2.imread("cat.jpg")#获取像素值px = img[200,200]print(px)print(img.item(200,200,0))img.itemset((200,200,0),100)print(img.item(200,200,0))
可以看到,对于指定的颜色通道的赋值时完全可以的。
2.查看图像属性
现在将要对图像的各个属性进行研究,图像属性包括行数、列数和通道数,图像数据类型,像素数等。
对于一个图像,我们使用shape可以返回行数、列数以及颜色通道的元数:
import cv2import numpy as npimg = cv2.imread("cat.jpg")print(img.shape)
输出的第三个数值代表的是图像的BGR三个通道的元数,也就是3。现在我们使用灰度图像做实验:
import cv2import numpy as npimg = cv2.imread("cat.jpg")img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)print(img.shape)
灰度图像在之后的教程中会进行讲解,这里先用做实验:
可以看到,如果图像是灰度的,则返回的元组仅包含行数和列数,因此这是检查加载的图像是灰度还是彩色的好方法。
通过size可以返回当前图像的所有的像素点的总数:
import cv2import numpy as npimg = cv2.imread("cat.jpg")print(img.size)
图像的数据类型可以通过dtype获得:
import cv2import numpy as npimg = cv2.imread("cat.jpg")print(img.dtype)
imread函数默认读取图像的格式就是uint8,所以返回的全部都是这个格式。在以后我们学习深度学习框架时会发现,uint8的图像数据格式用来进行模型训练时,做数据归一化(预处理阶段)会导致精度缺失,最后导致分割精度下降。当然这是后话,我们现在不提。
如果我们想修改图像的格式,我们需要用到astype函数,现在将图像修改为float32格式的(这种格式的图像被广泛的应用于深度学习的模型训练):
import cv2import numpy as npimg = cv2.imread("cat.jpg").astype(np.float32)print(img.dtype)
dtype在调试时非常重要,因为OpenCV-Python代码中的大量错误是由无效的数据类型引起的,我们在以后的学习中会经常遇到这些问题。
3.图像ROI
对于图像中的特定区域的选取我们称之为ROI,其实际上就是对图像的xy坐标进行操作,我们来看示例:
import cv2import numpy as npimg = cv2.imread("cat.jpg")husky = img[1:240,60:270]cv2.imshow("img",husky)cv2.waitKey(0)cv2.destroyAllWindows()
本质相当于截取某一部分图片,现在我们来做一些有意思的操作,将截取部分覆盖到图像的其他地方,本质相当于前面讲过的像素修改:
import cv2import numpy as npimg = cv2.imread("cat.jpg")husky = img[1:240,60:270]img[61:300,270:480] = huskycv2.imshow("img",img)cv2.waitKey(0)cv2.destroyAllWindows()
4.分割和合并图像通道
有时我们需要在B,G,R通道图像上单独进行操作。在这种情况下,需要将BGR图像分割为单个通道。需要使用split函数与merge函数,它们的作用分别为分离和合并:
b,g,r = cv2.split(img) #拆分图像通道img = cv2.merge((b,g,r))
此操作可以将BGR三通道分离出来,从而可以对某一通道进行操作,比如现在我们将R像素全部设置为0:
import cv2import numpy as npimg = cv2.imread("cat.jpg")b,g,r = cv2.split(img) #拆分图像通道img[:,:,2] = 0r = img[:,:,2]img = cv2.merge((b,g,r))cv2.imshow("img",img)cv2.waitKey(0)cv2.destroyAllWindows()
r则为R通道,看效果:
将红色通道去除后,我们的猫咪变的有点绿了。当然,大家还可以进行其他的通道的实验。
5.图像边框填充
如果要在图像周围创建边框(如相框),则可以使用函数cv2.copyMakeBorder()。它在卷积运算(很重要),零填充等方面有更多应用。
此函数采用以下参数:
cv2.copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]])
♦ src—输入图像
♦ top,bottom,left,right—相应方向上像素数的边框宽度
♦ value—cv2.BORDER_CONSTANT,cv2.BORDER_REFLECT,cv2.BORDER_REFLECT_101 or cv2.BORDER_DEFAULT ,cv2.BORDER_REPLICATE,cv2.BORDER_WRAP
cv2.BORDER_REFLECT_101或cv2.BORDER_DEFAULT
♦ 与上面相同,但略有改动,如下所示:gfedcb | abcdefgh | gfedcba
cv.BORDER_REPLICATE
♦ 最后一个像素在整个过程中被复制,像:aaaaaa |abcdefgh|hhhhhhh这样
cv.BORDER_WRAP
♦ 对称方向 像素互换 就像:cdefgh|abcdefgh|abcdefg 这样。
我们来看代码:
import cv2from matplotlib import pyplot as pltBLUE = [255,0,0]img1 = cv2.imread('cat.jpg')replicate = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REPLICATE)reflect = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT)reflect101 = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT_101)wrap = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_WRAP)constant= cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_CONSTANT,value=BLUE)plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL')plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')plt.show()
实验效果:
对于五个参数都进行了实验,可以看到明显的不同,当然,在这里为了方便图片对比显示,我们使用了matplotlib库,不过这属于python的知识,在这里就不一一介绍讲解了,大家也可以修改代码用OpenCV进行其他参数输出。
图像的算术运算
本次教程我们将概述图像的算数运算,众所周知,数学中有着加减乘除运算,同样的,图像也是如此,它的本质实际上就是一个矩阵,所以图像也存在着加法、减法、位运算等等算数运算。
1.加法
使用cv2.add()将两个图像相加,可以使用numpy中的矩阵加法来实现。但是在opencv中加法是饱和操作,也就是有上限值,numpy会对结果取模,综上,使用opencv的效果更好,我们来看函数实例:
cv2.add(img1, img2) # 进行图片的加和
参数说明:cv2.add将两个图片进行加和,大于255的使用255计数。
我们将使用以下两个图片作为实例:
来看代码:
import cv2img1 = cv2.imread("01.jpg")img2 = cv2.imread("02.jpg")res = cv2.add(img1,img2)cv2.imshow("res",res)cv2.waitKey(0)cv2.destroyAllWindows()
不难理解,第一幅图像白色部分像素部分为255,黑色部分像素为0,所以和第二幅图像加起来之后白色部分仍然是白色部分,因为加起来的值大于255时,默认取值255。
2.减法
减法运算就是两幅图像见对象像素的灰度值或彩色分量进行相减,它可以用于目标检测,需要用到函数cv2.subtract(),程序实现:
import cv2img1 = cv2.imread("01.jpg")img2 = cv2.imread("02.jpg")res = cv2.subtract(img1,img2)cv2.imshow("res",res)cv2.waitKey(0)cv2.destroyAllWindows()
3.乘法
图像的乘法运算就是将两幅图像对应的灰度值或彩色分量进行相乘。
乘运算的主要作用是抑制图像的某些区域,掩膜值置为1,否则置为0。乘运算有时也被用来实现卷积或相关的运算,其相关函数为cv2.multiply()。
以下为相关程序代码:
import cv2img1 = cv2.imread("01.jpg")img2 = cv2.imread("02.jpg")res = cv2.multiply(img1,img2)cv2.imshow("res",res)cv2.waitKey(0)cv2.destroyAllWindows()
4.除法
图像除运算就是两幅图像对应像素的灰度值或彩色分量进行相除。简单的出运算可以用于改变图像的灰度级。其相关函数为cv2.divide。
以下为代码部分:
5.图像融合
它实际上本质也是一个加法运算,但是这个加法运算跟普通的并不一样,我们可以理解为是一种加权的运算。
我们用函数来表示一个图像,前提是所有的图像尺寸是一样的,即图像矩阵的行列一样,通道数一样。
我们用 f0(x) 和 f1(x) 来表示输入的图像,用 g(x) 来表示输出图像,α表示比例( 0≤α≤1 ,一般来说,α取0和1没有太大意义),那我们能得到如下图所示的一个公式:
所以图像混合就是将两个图像按照一定的比例转存到另一个图像中。
首先需要看一下函数原型:
cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst
♦ src1—第一个输入数组。
♦ alpha—第一个数组元素的权重。
♦ src2—第二个输入数组,其大小和通道号与src1相同。
♦ beta—第二个数组元素的权重。
♦ gamma—标量加到每个和。
♦ dst—输出数组,其大小和通道数与输入数组相同。
♦ dtype—输出数组的可选深度;当两个输入数组的深度相同时,可以将dtype设置为-1,这等效于src1.depth()。
此函数可以用以下矩阵表达式进行代替:
dst = src1 * alpha + src2 * beta + gamma;
注意:由参数说明可以看出,被叠加的两幅图像必须是尺寸相同、类型相同的;并且,当输出图像array的深度为CV_32S时,这个函数就不适用了,这时候就会内存溢出或者算出的结果压根不对。
我们来看一下代码:
import cv2img1 = cv2.imread("01.jpg")img = cv2.imread("02.jpg")h, w, _ = img1.shapeimg2 = cv2.resize(img, (w,h), interpolation=cv2.INTER_AREA)alpha = 0.7beta = 1-alphagamma = 0img_add = cv2.addWeighted(img1, alpha, img2, beta, gamma)cv2.imshow('img_add',img_add)cv2.waitKey()cv2.destroyAllWindows()
效果:
此函数最大的缺陷就是需要两张图片尺寸必须完全一样,所以在实验时必须要注意。
6.按位运算
我们在学习数电时想必都学过逻辑运算,OpenCV中也有相关的运算。与或非这些想必就不必再多讲了,我们可以通过代码实验来熟悉:
1)与运算:
import cv2img1 = cv2.imread("01.jpg")img2 = cv2.imread("02.jpg")res = cv2.bitwise_and(img1,img2)cv2.imshow("res",res)cv2.waitKey()cv2.destroyAllWindows()
2)或运算:
import cv2img1 = cv2.imread("01.jpg")img2 = cv2.imread("02.jpg")res = cv2.bitwise_or(img1,img2)cv2.imshow("res",res)cv2.waitKey()cv2.destroyAllWindows()
可以看到,跟加法运算基本上类似。
3)非运算:
import cv2img1 = cv2.imread("01.jpg")img2 = cv2.imread("02.jpg")res = cv2.bitwise_not(img1,img2)cv2.imshow("res",res)cv2.waitKey()cv2.destroyAllWindows()
非运算在之后的学习中是非常有帮助的,它的以用来对二值化图像进行取反,然后方便进行形态学操作。
4)异或运算:
import cv2img1 = cv2.imread("01.jpg")img2 = cv2.imread("02.jpg")res = cv2.bitwise_xor(img1,img2)cv2.imshow("res",res)cv2.waitKey()cv2.destroyAllWindows()
关于图像的所有的基本运算就介绍到这里。
7.练习实例
现在带大家做一个好玩的小项目,题目是:用OpenCV完成一个幻灯片演示一幅图转成另一幅图,并在图像之间进行平滑过渡。
实际上,我们使用刚刚的线性加权函数就可以完成,我们只需要定义一个变量a,然后让其值小于一,变量的值依次递增。这样总体进行分析的话,第一幅图图像的加权值为a,第二幅图像的加权值为1-a,那么在一个循环里面它们会进行动态过渡,我们来看一下代码:
import cv2 as cvimg1 = cv.imread('01.jpg')img2 = cv.imread('02.jpg')l, h = img1.shape[0:2]img2_R = cv.resize(img2, (h, l))a=0cv.namedWindow('ppt',True)dst = cv.addWeighted(img1, a, img2_R, 1-a, -1)cv.imshow('ppt', dst)cv.waitKey(0)while a<1.0:dst = cv.addWeighted(img1, a, img2_R, 1-a, -1)cv.imshow('ppt', dst)cv.waitKey(100)a+=0.02cv.waitKey(0)cv.destroyAllWindows()
按下esc键开始幻灯片放映,由于效果为动态,此处不便展示,大家请自己实验,还是很有意思的。
扫码入群扫码添加管理员微信
加入“电子产品世界”粉丝交流群
↓↓↓↓点击,查看更多新闻
python opencv 图像切割_【OpenCV+Python】图像的基本操作与算术运算相关推荐
- python opencv 图像切割_使用Python+OpenCV进行图像处理(二)| 视觉入门
译者 | 磐石 编辑 | 安可 [前言]图像预处理对于整个图像处理任务来讲特别重要.如果我们没有进行恰当的预处理,无论我们有多么好的数据也很难得到理想的结果. 本篇是视觉入门系列教程的第二篇.整个视觉 ...
- python调整图像大小_使用Python调整图像大小
作者|Nicholas Ballard 编译|VK 来源|Towards Data Science 可以说,每一个"使用计算机的人"都需要在某个时间点调整图像的大小.MacOS的预 ...
- python opencv gpu加速_让Python下的OpenCV也能GPU加速!part.1
20200411更新: 经过评论区 @鹤汀凫渚 的指导,我成功的用最简单的方法在python中调用到了GPU加速后的函数,这里把这位朋友的评论贴出来供各位参考: 以下原文: 本文的核心目的就是加速,在 ...
- opencv自动裁切_荐Python Opencv 之 简单的视频裁剪功能的实现
Python Opencv 之 简单的视频裁剪功能的实现 目录 一.简单介绍 Python是一种跨平台的计算机程序设计语言.是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随 ...
- python图像检测_用Python实现通过哈希算法检测图片重复的教程
Iconfinder 是一个图标搜索引擎,为设计师.开发者和其他创意工作者提供精美图标,目前托管超过 34 万枚图标,是全球最大的付费图标库.用户也可以在 Iconfinder 的交易板块上传出售原创 ...
- python制作文字识别_用Python轻松进行图像文本识别
用Python轻松进行图像文本识别 作者:梅朵 微信公众号:实用办公编程技能 微信号:Excel-Python 最近,办公室的同事小李在整理一份报告,很多材料的电子版找不到了,都是纸质版的,纸质版上的 ...
- python 图片拼接成数字_用Python语言对任意图像进行m*n的均匀分块并拼接还原(思路非常清晰,步骤简单)...
目录 1.读取原始图像 2.网格划分,将图像划分为m*n块 2.1分块后图像的存储问题 2.2图像的裁剪 2.3图像长宽的整除问题 方法一:四舍五入法 方法二:图像缩放法 方法三:非均分方法 3.显示 ...
- 抖音是用python写的吗_用 Python 实现抖音尬舞机
原标题:用 Python 实现抖音尬舞机 如今说到体感游戏,大家一定都不陌生,比如微软的 Kinect.任天堂的 Switch,都曾是游戏业的革命性产品.而另一款网红产品-抖音,也在去年底上线过一个& ...
- python图片批量处理器_用python给图片批量打水印
之前写菲律宾游记,想给自己的照片批量打上水印,首先想到的就是用Python实现给图片加文字,然后写个循环. 做过图像识别的,应该知道OpenCV,其中cv2.putText()函数,就可以实现在图片 ...
最新文章
- android ffmpeg 编码h264,Mac系统下ffmpeg+h264+flv编码的android录制屏幕实现2
- 算法笔记之分支限界法
- [一维粒子模拟 version3.6]renormalization
- 【网址收藏】Percona-xtraDB-cluster的安装、配置和使用 PXC
- SpringCloud Eureka参数配置项详解
- 打包签名时出现Conversion to Dalvik format failed with error 1
- 关于用FOMR提交编码的问题
- 基于Transformers+CNN/LSTM/GRU的文本分类
- 学习笔记-Speed-Win
- linux检测nfc,kali linux 能用哪些nfc读卡器
- 用得上的商学课-老路
- python 读取网络位置的文件
- SEO内链优化,网站内部链接优化方法
- HTML+CSS+JS大作业:生态环境网站设计——环境保护主题-绿色环保 (9页) web期末作业设计网页_绿色环保大学生网页设计作业成品
- FinalShell连接超时解决方法
- ipynb文件转py文件
- C语言读写中文时出现乱码的解决
- 带宽与码元的关系_通信中的带宽关系、以及码元、波特率、比特率、奈奎斯特带宽...
- 开传奇大概需要什么条件
- 交换机ARP代理详解
热门文章
- VSCode+BeetleX.VueHost开发Vue应用
- 跟我一起学Redis之Redis事务简单了解一下
- 5G在工业互联网应用的机遇与挑战
- ASP.NET Core Blazor WebAssembly 之 .NET JavaScript互调
- IBM 声明对 Google 违背承诺未将 Istio 贡献给 CNCF 表示失望
- SQL Server 分页+json分享
- Asp.Net Core 混合全球化与本地化支持
- C# 结合 Golang 开发
- 13张PPT带你了解主动式消息队列处理集群
- 基于Dapper的开源Lambda扩展,且支持分库分表自动生成实体