opencv图像的基本操作3
1、获取像素并修改
读取一副图像,根据像素的行和列的坐标获取它的像素值,对于RGB图像而言,返回RGB的值,对于灰度图则返回灰度值
import cv2
import numpy
img = cv2.imread('1.jpg')
px = img[100, 100]
print(px) #获取图像的(100,100)的3维矩阵
Blue = img[100, 100, 0]
Gray = img[100, 100, 1]
Red = img[100, 100, 2]
print(Blue, Gray, Red)#打印三色图的灰度值,默认BGR
for i in img[100, 100]:# 遍历矩阵
print(i) print(img.item(100, 100, 2))#快速获取矩阵值
img.itemset((100, 100, 2), 99)#快速修改矩阵值
执行结果:
[254 148 125]
254 148 125
254
148
125
125
2、获取图像的属性
图像属性包括:行,列,通道,图像数据类型,像素数目等
2.1 img.shape可以获得图像的形状,返回值是一个包含行数,列数,通道数的元组
如果图像是灰度图,返回值仅有行数和列数,所以通过检查返回值可以判断是灰度图还是彩色图
port cv2
import numpy
img = cv2.imread('1.jpg')
print(img.shape)
img1 = cv2.imread('1.jpg', 0)
print(img1.shape)
执行结果:
(375, 500, 3)
(375, 500)
2.2 img.size可以返回图像的像素数目
print(img.size)#img.size可以返回图像的像素数目
执行结果:562500
2.3 img.dtype返回图像的数据类型,在debug时很重要,因为OpenCV-Python代码中经常出现数据类型的不一致
print(img.dtype)
结果:
unit8
3、 图像转换——cvtColor()
在日常生活中,我们看到的大多数彩色图像都是RGB类型,但是在图像处理过程中,常常需要用到灰度图像、二值图像、HSV、HSI等颜色,OpenCV提供了 cvtColor() 函数实现这些功能。
OpenCV中 cvtColor() 函数形式如下所示:
dst = cv2.cvtColor(src, code[, dst[, dstCn]])
其中,参数:
src 表示输入图像,需要进行颜色空间变换的原图像;
dst 表示输出图像,其大小和深度与src一致;
code 表示转换的代码或标识;
dstCn 表示目标图像通道数,其值为0时,则有src和code决定。
cvtColor() 函数的作用是将一个图像从一个颜色空间转换到另一个颜色空间,其中,RGB是指Red、Green和Blue,一幅图像由这三个通道(channel)构成;Gray表示只有灰度值一个通道;HSV包含Hue(色调)、Saturation(饱和度)和Value(亮度)三个通道。在OpenCV中,常见的颜色空间转换标识包括CV_BGR2BGRA、CV_RGB2GRAY、CV_GRAY2RGB、CV_BGR2HSV、CV_BGR2XYZ、CV_BGR2HLS等。
import cv2
import numpy as np
import matplotlib.pyplot as plt
import cv2
import numpy as np
import matplotlib.pyplot as plt # 读取原始图像
img_BGR = cv2.imread('1.jpg') # BGR转换为RGB
img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB) # 灰度化处理
img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY) # BGR转HSV
img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV) # BGR转YCrCb
img_YCrCb = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb) # BGR转HLS
img_HLS = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HLS) # BGR转XYZ
img_XYZ = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2XYZ) # BGR转LAB
img_LAB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2LAB) # BGR转YUV
img_YUV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YUV) # 调用matplotlib显示处理结果
titles = ['BGR', 'RGB', 'GRAY', 'HSV', 'YCrCb', 'HLS', 'XYZ', 'LAB', 'YUV']
images = [img_BGR, img_RGB, img_GRAY, img_HSV, img_YCrCb,
img_HLS, img_XYZ, img_LAB, img_YUV]
for i in range(9):
plt.subplot(3, 3, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
44 cv2.waitKey(0)
cv2.destroyAllWindows()
4、图像的二值化
定义:图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。
灰度值0:黑,灰度值255:白
一幅图像包括目标物体、背景还有噪声,要想从多值的数字图像中直接提取出目标物体,常用的方法就是设定一个阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。这是研究灰度变换的最特殊的方法,称为图像的二值化(Binarization)。
4.1 固定阈值二值化threshold
cv2.threshold(img, threshold, maxval,type)
参数:
img是要二值化的图像,维单通道图像
threshold是设定的阈值
maxval是当灰度值大于(或小于)阈值时将该灰度值赋成的值
type规定的是当前二值化的方式
破折线为将被阈值化的值;虚线为阈值
4.1.1 cv2.THRESH_BINARY 大于阈值的部分被置为255,小于部分被置为0
4.1.2 cv2.THRESH_BINARY_INV 大于阈值部分被置为0,小于部分被置为255
4.1.3 cv2.THRESH_TRUNC 大于阈值部分被置为threshold,小于部分保持原样
4.1.4 cv2.THRESH_TOZERO 小于阈值部分被置为0,大于部分保持不变
4.1.5 cv2.THRESH_TOZERO_INV 大于阈值部分被置为0,小于部分保持不变
其实还有很重要的cv2.THRESH_OTSU 作为图像自适应二值化的一个很优的算法Otsu大津算法的参数:
使用为cv2.threshold(img, 0, 255, cv2.THRESH_OTSU )
函数有四个参数,第一个为原图像,第二个为阈值0,OTSU会自动寻找阈值,第三个为高于阈值时赋予的新值,第四个为在这里选择大津算法。该函数有两个返回值,第一个retVal(得到的阈值值),第二个就是阈值化后的图像。
import cv2
img = cv2.imread('huawei.jpg', cv2.IMREAD_GRAYSCALE) # 读取灰度图像
img = cv2.resize(img, (300, 300), interpolation=cv2.INTER_AREA)
cv2.imshow('img',img)
cv2.waitKey(0) ret, binary = cv2.threshold(img, 175, 255, cv2.THRESH_BINARY)
ret, binaryinv = cv2.threshold(img, 175, 255, cv2.THRESH_BINARY_INV)
ret, trunc = cv2.threshold(img, 175, 255, cv2.THRESH_TRUNC)
ret, tozero = cv2.threshold(img, 175, 255, cv2.THRESH_TOZERO)
ret, tozeroinv = cv2.threshold(img, 175, 255, cv2.THRESH_TOZERO_INV)
print(ret) #阈值 cv2.imshow('binary', binary)
cv2.imshow('binaryinv', binaryinv)
cv2.imshow('trunc', trunc)
cv2.imshow('tozero', tozero)
cv2.imshow('tozeroinv', tozeroinv)
cv2.waitKey(0)
执行结果:
4.2 自适应阈值化操作:adaptiveThreshold()函数
当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。
自适应阈值则,是根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值。这样做的好处:
(1)每个像素位置处的二值化阈值不是固定不变的,而是由其周围邻域像素的分布来决定的。
(2)亮度较高的图像区域的二值化阈值通常会较高,而亮度较低的图像区域的二值化阈值则会相适应地变小。
(3)不同亮度、对比度、纹理的局部图像区域将会拥有相对应的局部二值化阈值
OpenCV中提供了自适应阈值化函数adaptiveThreshold(),该函数有两种自适应阈值化类型参数可供选择,用来对当前像素点与领域像素块进行阈值计算。常用的自适应阈值类型有:1)局部邻域块的平均值;2)局部邻域块的高斯加权和。
函数定义:
def adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None):
参数:
第一个参数 src 指原图像,原图像应该是灰度图。
第二个参数 x 指当像素值高于(有时是小于,根据thresholdType决定)阈值时应该被赋予的新的像素值
第三个参数 adaptive_method 指: CV_ADAPTIVE_THRESH_MEAN_C 或 CV_ADAPTIVE_THRESH_GAUSSIAN_C
第四个参数 threshold_type 指取阈值类型:必须是下者之一 • CV_THRESH_BINARY,大于阈值的部分被置为255,小于部分被置为0
• CV_THRESH_BINARY_INV 大于阈值的部分被置为0,小于部分被置为255
第五个参数 block_size 指用来计算阈值的象素邻域大小: 3, 5, 7, ...
第六个参数 C 指与方法有关的参数。对方法CV_ADAPTIVE_THRESH_MEAN_C 和 CV_ADAPTIVE_THRESH_GAUSSIAN_C, 它是一个从均值或加权均值提取的常数, 尽管它可以是负数。
参数三和六内容的解释:自适应阈值化计算大概过程是为每一个象素点单独计算的阈值,即每个像素点的阈值都是不同的,就是将该像素点周围B*B区域内的像素加权平均,然后减去一个常数C,从而得到该点的阈值。B由参数5指定,常数C由参数6指定。
参数3:
ADAPTIVE_THRESH_MEAN_C,为局部邻域块的平均值。该算法是先求出块中的均值,再减去常数C。
ADAPTIVE_THRESH_GAUSSIAN_C ,为局部邻域块的高斯加权和。该算法是在区域中(x,y)周围的像素根据高斯函数按照他们离中心点的距离进行加权计算, 再减去常数C。
举个例子:
如果使用平均值方法,平均值mean为190,差值delta(即常数C)为30。选则方式 CV_THRESH_BINARY,那么灰度小于160的像素为0,大于等于160的像素为255。如下图:
如果是反向二值化选择方式 CV_THRESH_BINARY_INV,如下图:
delta(常数C)选择负值也是可以的。
采用方法 CV_ADAPTIVE_THRESH_MEAN_C(邻域平均),阈值类型:CV_THRESH_BINARY(大于阈值255), 阈值的象素邻域大小 block_size 选取3,参数C 取5:
C=5
代码演示
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('huawei.jpg')
GrayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 中值滤波
GrayImage= cv2.medianBlur(GrayImage,5) #固定值二值化 大于阈值的部分被置为255,小于部分被置为0
ret, th1 = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_BINARY) #3 为Block size, C值为5
th2 = cv2.adaptiveThreshold(GrayImage, 255, cv2.ADAPTIVE_THRESH_MEAN_C,\
cv2.THRESH_BINARY, 3, 5)
th3 = cv2.adaptiveThreshold(GrayImage, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
cv2.THRESH_BINARY, 3, 5)
titles = ['Gray Image', 'Global Thresholding (v = 127)',
'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [GrayImage, th1, th2, th3]
for i in range(4):
plt.subplot(2, 2, i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
5、cv2.findContours()函数来查找检测物体的轮廓
cv2.findContours()函数
函数的原型为
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])
opencv2返回两个值:contours:hierarchy。注:opencv3会返回三个值,分别是img, countours, hierarchy
参数
第一个参数是寻找轮廓的图像;
第二个参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口):
cv2.RETR_EXTERNAL表示只检测外轮廓
cv2.RETR_LIST检测的轮廓不建立等级关系
cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
cv2.RETR_TREE建立一个等级树结构的轮廓。
第三个参数method为轮廓的近似办法
cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
返回值
cv2.findContours()函数返回两个值,一个是轮廓本身,还有一个是每条轮廓对应的属性。
contour返回值
cv2.findContours()函数首先返回一个list,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。这个概念非常重要。在下面drawContours中会看见。通过
5.图像ROI对图像的特定区域操作。ROI是使用numpy索引来获得的。
简单的说就是对图像感兴趣的区域,机器视觉、图像处理中,从被处理的图像以方框、圆、椭圆、不规则多边形等方式勾勒出需要处理的区域,称为感兴趣区域ROI。举个例子来说:有一副图片,图片上有各种动物,但是你只喜欢图片里的狗,那么这个狗所在的区域就是感兴趣的区域(ROI)。
(1) 矩形ROI,直接使用切片,简单粗暴
import cv2 img = cv2.imread("1.jpg")
roi = img[50:120, 50:100]# 前面高度截取,后面横向截取
cv2.imshow('roi', roi)
cv2.waitKey(0)
cv2.destroyAllWindows()
(2)一些常用函数选取感兴趣的区域
补充:a、numpy.zeros() 用法
b、Python中图像的缩放 resize()函数的应用
6、拆分及合并图像通道
有时需要对RGB三个通道分别操作,这就需要拆分RGB为单个通道。有时需要把独立的通道的图片合成一个RGB
方法1:使用OpenCV自带的split函数
import cv2
from matplotlib import pyplot as plt
import numpy as np
img = cv2.imread('1.jpg')
# b, g, r = cv2.split(img)#拆分图像
b = cv2.split(img)[0]
g = cv2.split(img)[1]
r = cv2.split(img)[2]
img1 = cv2.merge([r, g, b]) titles = ['R', 'G', 'B', 'img1']
images = [r, g, b, img1]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show() cv2.waitKey(0)
cv2.destroyAllWindows()
执行结果:
方法2:直接操作NumPy数组来达到这一目的
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread("1.jpg")
print(img.shape[0], img.shape[1], img.dtype) b = np.zeros((img.shape[0], img.shape[1]), dtype=img.dtype)
g = np.zeros((img.shape[0], img.shape[1]), dtype=img.dtype)
r = np.zeros((img.shape[0], img.shape[1]), dtype=img.dtype) b[:, :] = img[:, :, 0]
g[:, :] = img[:, :, 1]
r[:, :] = img[:, :, 2] mergedByNp = np.dstack([b,g,r]) #合并图像
titles = ['R', 'G', 'B', 'mergedByNp']
images = [r, g, b, mergedByNp]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show() cv2.waitKey(0)
cv2.destroyAllWindows()
注意:cv2.split()是比较耗时的操作,能用numpy就尽量使用。
7、为图像扩边(填充)
https://blog.csdn.net/zfjBIT/article/details/86655182
opencv图像的基本操作3的更多相关文章
- opencv入门系列教学(五)图像的基本操作(像素值、属性、ROI和边框)
0.序言 每个图像是由一个个点组成的,而这些点可以表示为像素值的形式. 这篇博客里我们将学会: 访问像素值并修改它们 . 访问图像属性 . 设置感兴趣区域(ROI) . 分割和合并图像. 对于图像的基 ...
- OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放
这篇已经写得很好,真心给作者点个赞.题目都是直接转过来的,直接去看吧. Reference Link : http://blog.csdn.net/poem_qianmo/article/detail ...
- 【OpenCV新手教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26157633 作者:毛星云(浅墨) ...
- Opencv 图像叠加 添加水印
Opencv 图像叠加 添加水印 C++: void Mat::copyTo(OutputArray m) const C++: void Mat::copyTo(OutputArray m, Inp ...
- opencv图像读取-imread
前言 图像的读取和保存一定要注意imread函数的各个参数及其意义,尽量不要使用默认参数,否则就像数据格式出现错误(here)一样,很难查找错误原因的: re: 1.opencv图像的读取与保存; 完
- 学习 opencv---(12)OpenCV 图像金字塔:高斯金字塔,拉普拉斯金字塔与图片尺寸缩放
在这篇文章里,我们一起学习下 图像金字塔 的一些基本概念,如何使用OpenCV函数pyrUp和pyrDown 对图像进行向上和向下采样,以及了解专门用于缩放图像尺寸的resize函数的用法.此博文一共 ...
- [OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget(第二部分)
本文译自:http://www.robot-home.it/blog/en/software/tutorial-opencv-qt-opengl-widget-per-visualizzare-imm ...
- [OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget (第一部分)
本文译自:http://www.robot-home.it/blog/en/software/tutorial-opencv-qt-opengl-widget-per-visualizzare-imm ...
- 关于OpenCV图像操作的默认参数问题
本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/51559490 在使用OpenCV以及其 ...
随机推荐
- axios 利用new FileReader() 下载文件获取返回的错误信息
this.axios({ method: "post", url: url, data: data, ...
- JavaScript —— 字符串中使用正则表达式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- MySQL06-- mysql索引
目录 一.索引介绍 1.什么是索引 2.索引类型介绍 3.索引管理 5.索引操作 6.前缀索引 7.联合索引 8.创建索引总结: 一.索引介绍 1.什么是索引 1)索引就好比一本书的目录,它能让你更快 ...
- 关于如何测试cpu性能的命令操作 linux系统
for i in `seq 1 $(cat /proc/cpuinfo |grep "physical id" |wc -l)`; do dd if=/dev/zero of=/d ...
- shlwapi.h文件夹文件是否存在
{ if( NULL == lpszFileName) { return FALSE; } if (PathFileExists(lpszFileName)) { return TRUE; } els ...
- CSAW CTF Qualification Round 2018 - shell->code
原题 Linked lists are great! They let you chain pieces of data together. nc pwn.chal.csaw.io 9005 链接:h ...
- 唐太宗灵州勒石 TANGTAIZONGLINZHOULESHI
唐太宗灵州勒石 唐贞观二十年(646年),在唐军和回纥部落联合打败突厥薛延陀部后,原归附薛延陀部的回纥.拔野古.斛薛等部族,越过贺兰山,进入了今宁夏的银川.吴忠一带地区.这些总族向唐朝提出,愿意臣服唐 ...
- kali网络源配置
使用vim对sources.list文件进行修改: $ vim /etc/apt/sources.list 随便挑选一个源添加到该文件中 ----------------------------- ...
- vue项目中使用echarts地图
第一步.npm install echarts 第二部.在main.js中引入 第三步.创建组件,并且用this.$echarts.init初始化echarts <template> &l ...
- netty-Selector
上图中加入一句: socketChannel.configureBlocking(false);//设置为非阻塞的 keyIterator.clear(); 每连接一个SocketChannel 都会 ...