opencv图像的基本操作3

1、获取像素并修改

读取一副图像,根据像素的行和列的坐标获取它的像素值,对于RGB图像而言,返回RGB的值,对于灰度图则返回灰度值

 1 import cv2
 2 import numpy
 3 img = cv2.imread('1.jpg')
 4 px = img[100, 100]
 5 print(px) #获取图像的(100,100)的3维矩阵
 6 Blue = img[100, 100, 0]
 7 Gray = img[100, 100, 1]
 8 Red = img[100, 100, 2]
 9 print(Blue, Gray, Red)#打印三色图的灰度值,默认BGR
10 for i in img[100, 100]:# 遍历矩阵
11     print(i)
12 
13 print(img.item(100, 100, 2))#快速获取矩阵值
14 img.itemset((100, 100, 2), 99)#快速修改矩阵值

执行结果:

[254 148 125]
254 148 125
254
148
125
125

 2、获取图像的属性

 图像属性包括:行,列,通道,图像数据类型,像素数目等

2.1 img.shape可以获得图像的形状,返回值是一个包含行数,列数,通道数的元组

如果图像是灰度图,返回值仅有行数和列数,所以通过检查返回值可以判断是灰度图还是彩色图

1 port cv2
2 import numpy
3 img = cv2.imread('1.jpg')
4 print(img.shape)
5 img1 = cv2.imread('1.jpg', 0)
6 print(img1.shape)

 执行结果:

(375, 500, 3)
(375, 500)

2.2 img.size可以返回图像的像素数目 

1 print(img.size)#img.size可以返回图像的像素数目
2 执行结果:562500

 2.3 img.dtype返回图像的数据类型,在debug时很重要,因为OpenCV-Python代码中经常出现数据类型的不一致

1 print(img.dtype)
2 结果:
3 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等。

 1   import cv2
 2   import numpy as np
 3   import matplotlib.pyplot as plt
 4   import cv2
 5   import numpy as np
 6   import matplotlib.pyplot as plt
 7   
 8  # 读取原始图像
 9   img_BGR = cv2.imread('1.jpg')
10  
11  # BGR转换为RGB
12  img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)
13  
14  # 灰度化处理
15  img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY)
16  
17  # BGR转HSV
18  img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV)
19  
20  # BGR转YCrCb
21  img_YCrCb = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb)
22  
23  # BGR转HLS
24  img_HLS = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HLS)
25  
26  # BGR转XYZ
27  img_XYZ = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2XYZ)
28  
29  # BGR转LAB
30  img_LAB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2LAB)
31  
32  # BGR转YUV
33  img_YUV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YUV)
34  
35  # 调用matplotlib显示处理结果
36  titles = ['BGR', 'RGB', 'GRAY', 'HSV', 'YCrCb', 'HLS', 'XYZ', 'LAB', 'YUV']
37  images = [img_BGR, img_RGB, img_GRAY, img_HSV, img_YCrCb,
38            img_HLS, img_XYZ, img_LAB, img_YUV]
39  for i in range(9):
40      plt.subplot(3, 3, i + 1), plt.imshow(images[i], 'gray')
41      plt.title(titles[i])
42      plt.xticks([]), plt.yticks([])
43  plt.show()
44  cv2.waitKey(0)
45  cv2.destroyAllWindows()

 

4、图像的二值化

定义:图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。

灰度值0:黑,灰度值255:白

   一幅图像包括目标物体、背景还有噪声,要想从多值的数字图像中直接提取出目标物体,常用的方法就是设定一个阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。这是研究灰度变换的最特殊的方法,称为图像的二值化(Binarization)。

4.1 固定阈值二值化threshold
cv2.threshold(img, threshold, maxval,type)

参数:

1 img是要二值化的图像,维单通道图像
2 threshold是设定的阈值
3 maxval是当灰度值大于(或小于)阈值时将该灰度值赋成的值
4 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(得到的阈值值),第二个就是阈值化后的图像。

 1 import cv2
 2 img = cv2.imread('huawei.jpg', cv2.IMREAD_GRAYSCALE) # 读取灰度图像
 3 img = cv2.resize(img, (300, 300), interpolation=cv2.INTER_AREA)
 4 cv2.imshow('img',img)
 5 cv2.waitKey(0)
 6 
 7 ret, binary = cv2.threshold(img, 175, 255, cv2.THRESH_BINARY)
 8 ret, binaryinv = cv2.threshold(img, 175, 255, cv2.THRESH_BINARY_INV)
 9 ret, trunc = cv2.threshold(img, 175, 255, cv2.THRESH_TRUNC)
10 ret, tozero = cv2.threshold(img, 175, 255, cv2.THRESH_TOZERO)
11 ret, tozeroinv = cv2.threshold(img, 175, 255, cv2.THRESH_TOZERO_INV)
12 print(ret) #阈值
13 
14 cv2.imshow('binary', binary)
15 cv2.imshow('binaryinv', binaryinv)
16 cv2.imshow('trunc', trunc)
17 cv2.imshow('tozero', tozero)
18 cv2.imshow('tozeroinv', tozeroinv)
19 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

代码演示

 1 import cv2
 2 import numpy as np
 3 from matplotlib import pyplot as plt
 4 img = cv2.imread('huawei.jpg')
 5 GrayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 6 # 中值滤波
 7 GrayImage= cv2.medianBlur(GrayImage,5)
 8 
 9 #固定值二值化 大于阈值的部分被置为255,小于部分被置为0
10 ret, th1 = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_BINARY)
11 
12 #3 为Block size, C值为5
13 th2 = cv2.adaptiveThreshold(GrayImage, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
14                     cv2.THRESH_BINARY, 3, 5)
15 th3 = cv2.adaptiveThreshold(GrayImage, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
16                     cv2.THRESH_BINARY, 3, 5)
17 titles = ['Gray Image', 'Global Thresholding (v = 127)',
18 'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
19 images = [GrayImage, th1, th2, th3]
20 for i in range(4):
21    plt.subplot(2, 2, i+1), plt.imshow(images[i], 'gray')
22    plt.title(titles[i])
23    plt.xticks([]), plt.yticks([])
24 plt.show()

 

 5、cv2.findContours()函数来查找检测物体的轮廓

cv2.findContours()函数

函数的原型为

1 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,直接使用切片,简单粗暴

1 import cv2
2 
3 img = cv2.imread("1.jpg")
4 roi = img[50:120, 50:100]# 前面高度截取,后面横向截取
5 cv2.imshow('roi', roi)
6 cv2.waitKey(0)
7 cv2.destroyAllWindows()

 (2)一些常用函数选取感兴趣的区域

补充:a、numpy.zeros() 用法

b、Python中图像的缩放 resize()函数的应用

详细查看 

6、拆分及合并图像通道 

 有时需要对RGB三个通道分别操作,这就需要拆分RGB为单个通道。有时需要把独立的通道的图片合成一个RGB

方法1:使用OpenCV自带的split函数

 1 import cv2
 2 from matplotlib import pyplot as plt
 3 import numpy as np
 4 img = cv2.imread('1.jpg')
 5 # b, g, r = cv2.split(img)#拆分图像
 6 b = cv2.split(img)[0]
 7 g = cv2.split(img)[1]
 8 r = cv2.split(img)[2]
 9 img1 = cv2.merge([r, g, b])
10 
11 titles = ['R', 'G', 'B', 'img1']
12 images = [r, g, b, img1]
13 for i in range(4):
14     plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
15     plt.title(titles[i])
16     plt.xticks([]), plt.yticks([])
17 plt.show()
18 
19 cv2.waitKey(0)
20 cv2.destroyAllWindows()

执行结果:

方法2:直接操作NumPy数组来达到这一目的

 1 import cv2
 2 import numpy as np
 3 from matplotlib import pyplot as plt
 4 img = cv2.imread("1.jpg")
 5 print(img.shape[0], img.shape[1], img.dtype)
 6 
 7 b = np.zeros((img.shape[0], img.shape[1]), dtype=img.dtype)
 8 g = np.zeros((img.shape[0], img.shape[1]), dtype=img.dtype)
 9 r = np.zeros((img.shape[0], img.shape[1]), dtype=img.dtype)
10 
11 b[:, :] = img[:, :, 0]
12 g[:, :] = img[:, :, 1]
13 r[:, :] = img[:, :, 2]
14 
15 mergedByNp = np.dstack([b,g,r])  #合并图像
16 titles = ['R', 'G', 'B', 'mergedByNp']
17 images = [r, g, b, mergedByNp]
18 for i in range(4):
19     plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
20     plt.title(titles[i])
21     plt.xticks([]), plt.yticks([])
22 plt.show()
23 
24 cv2.waitKey(0)
25 cv2.destroyAllWindows()

 注意:cv2.split()是比较耗时的操作,能用numpy就尽量使用。

 7、为图像扩边(填充)

https://blog.csdn.net/zfjBIT/article/details/86655182

原文地址:https://www.cnblogs.com/weststar/p/11506300.html