Python+OpenCV 图像处理系列(4)—— 图像像素的读写、算术运算、逻辑运算及像素的统计

1. 像素的读写

可以根据像素的行和列的坐标获取它的像素值。对 BGR 图像而言,返回值为 B,G,R 的值。

  • img.shape 可以获取图像的形状。它的返回值是一个包含行数 h,列数 w,通道数 ch 的元组。注意:如果图像是灰度图,返回值仅有行数和列数。所以通过检查这个返回值就可以知道加载的是灰度图还是彩色图。
  • img.size 可以返回图像的像素数目 (h * w * ch)
  • img.dtype 返回的是图像的数据类型:
import cv2

image_name = "img/003.jpg"
img = cv2.imread(image_name)
cv2.imshow("origin", img)

high, wide, channel = img.shape
print "high is {0}, wide is {1}, channel is {2}".format(high, wide, channel)
# high is 198, wide is 198, channel is 3

for row in range(high):
    for col in range(wide):
        b, g, r = img[row, col]
        b = 255 - b
        g = 255 - g
        r = 255 - r
        img[row, col] = b, g, r		# 修改像素值

cv2.imshow("output", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

显示结果:
原图和修改后的图片
如果上面的难以理解,可以看下面的这些操作,希望能帮助读者更好的理解。

>>> a = np.array([[[1,  2],  [3,4], [5, 6]], [[11,  22],  [33,44], [55, 66]]])
>>> a.shape
(2, 3, 2)
>>> a
array([[[ 1,  2],
        [ 3,  4],
        [ 5,  6]],

       [[11, 22],
        [33, 44],
        [55, 66]]])
        
>>> a.ndim
3
>>> a.size
12
>>> a[0, 1]
array([3, 4])
>>> a[1, 2]
array([55, 66])
>>> h, w = a[1, 2]
>>> h,w
(55, 66)

2. 像素的算术运算

图像像素也可以进行加、减、乘、除操作,但是必须要注意,进行算术运算操作的时,必须要保证两幅图像的大小、数据类型和通道数目必须相同

  • OpenCV 中的加法与 Numpy 的加法是有所不同的。OpenCV 的加法是一种饱和操作,而 Numpy 的加法是一种模操作。这种差别在你对两幅图像进行加法时会更加明显。OpenCV 的结果会更好一点。所以我们尽量使用 OpenCV 中的函数。

使用示例如下:

import cv2
import numpy as np

img1 = cv2.imread("img/003.jpg")
img2 = cv2.imread("img/003_gray.jpg")

cv2.imshow("img1", img1)
cv2.imshow("img2", img2)

h, w, ch = img1.shape

add_result = np.zeros(img1.shape, img1.dtype)
cv2.add(img1, img2, add_result)
cv2.imshow("add_result", add_result)


sub_result = np.zeros(img1.shape, img1.dtype)
cv2.subtract(img1, img2, sub_result)
cv2.imshow("sub_result", sub_result)

mul_result = np.zeros(img1.shape, img1.dtype)
cv2.multiply(img1, img2, mul_result)
cv2.imshow("mul_result", mul_result)


div_result = np.zeros(img1.shape, img1.dtype)
cv2.divide(img1, img2, div_result)
cv2.imshow("div_result", div_result)
cv2.waitKey(0)
cv2.destroyAllWindows()

操作前的两幅图像
操作后的两幅图像

3. 像素的逻辑运算

这里包括的按位操作有:AND,OR,NOT,XOR 等。当我们提取图像的一部分,选择非矩形 ROI 时这些操作会很有用。下面的例子就是教给我们如何改变一幅图的特定区域。

import cv2
import numpy as np

# create img one
img1 = np.zeros(shape=(200, 200, 3), dtype=np.uint8)
img1[50:100, 50:100, 1] = 255
img1[50:100, 50:100, 2] = 255
cv2.imshow("img1", img1)

# create img two
img2 = np.zeros(shape=(200, 200, 3), dtype=np.uint8)
img2[75:150, 75:150, 2] = 255
cv2.imshow("img2", img2)

dst1 = cv2.bitwise_and(img1, img2)
dst2 = cv2.bitwise_or(img1, img2)
dst3 = cv2.bitwise_xor(img1, img2)

cv2.imshow("dst1", dst1)
cv2.imshow("dst2", dst2)
cv2.imshow("dst3", dst3)

img4 = cv2.imread("img/003.jpg")
dst4 = cv2.bitwise_not(img4)

cv2.imshow("dst4", dst4)
cv2.waitKey(0)
cv2.destroyAllWindows()

原始图片
逻辑操作后的结果

4. 像素的统计

像素值统计涉及到的知识点有以下几个

  • 最小(min)
  • 最大(max)
  • 均值(mean)
  • 标准方差(standard deviation)

OpenCV 相关的 API 知识点

  • 最大最小值 minMaxLoc
  • 计算均值与标准方差 meanStdDev

注意:像素值统计必须是单通道的图片,所以 cv2.imread 时必须加上图片的载入类型。
源码中有如下提示:

'''
The function do not work with multi-channel arrays. If you need to find minimum or maximum
elements across all the channels, use Mat::reshape first to reinterpret the array as
single-channel.
'''
import cv2
import numpy as np

img = cv2.imread("img/003.jpg", cv2.IMREAD_GRAYSCALE)

minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(img)
print minVal, maxVal, minLoc, maxLoc    # 0.0 255.0 (128, 24) (120, 12)
means, stddev = cv2.meanStdDev(img)
print means, stddev     # [[97.23278237]] [[45.80720813]]

img[np.where(img < means)] = 0
img[np.where(img > means)] = 255

cv2.imshow("binary", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果图

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值