暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

OpenCV-Python - 核心功能 - 矩阵的掩码操作

数据库杂货铺 2022-01-17
901

矩阵的掩码操作

 

矩阵的掩码操作非常简单。其思想是,我们根据掩码矩阵(也称为核)重新计算图像中每个像素的值。此掩码保存的值将调整相邻像素(和当前像素)对新像素值的影响程度。从数学的观点来看,我们用指定的值进行加权平均。

 

测试用例

 

让我们考虑图像对比度增强方法的问题。基本上,我们想对图像的每个像素应用下面的公式:

 


I(i,j)=5I(i,j)[I(i1,j)+I(i+1,j)+I(i,j1)+I(i,j+1)]



I(i,j)M,where M=ij10+110100151+1010


第一种表示法是使用公式,而第二种是第一种表示法的压缩版本,使用掩码。使用掩码时,将掩码矩阵的中心(在上例中标记为 0-0索引) 放在想要计算的像素上。这2种方法是一样的,但是在大矩阵的情况下后一种表示法更容易理解。

 

代码

 

from __future__ import print_function
import sys
import time
import numpy as np
import cv2 as cv


def is_grayscale(my_image):
return len(my_image.shape) < 3


def saturated(sum_value):
if sum_value > 255:
sum_value = 255
if sum_value < 0:
sum_value = 0
return sum_value


def sharpen(my_image):
if is_grayscale(my_image):
height, width = my_image.shape
else:
my_image = cv.cvtColor(my_image, cv.CV_8U)
height, width, n_channels = my_image.shape
result = np.zeros(my_image.shape, my_image.dtype)

for j in range(1, height - 1):
for i in range(1, width - 1):
if is_grayscale(my_image):
sum_value = 5 * my_image[j, i] - my_image[j + 1, i] - my_image[j - 1, i] \
- my_image[j, i + 1] - my_image[j, i - 1]
result[j, i] = saturated(sum_value)
else:
for k in range(0, n_channels):
sum_value = 5 * my_image[j, i, k] - my_image[j + 1, i, k] \
- my_image[j - 1, i, k] - my_image[j, i + 1, k]\
- my_image[j, i - 1, k]
result[j, i, k] = saturated(sum_value)

return result


def main(argv):
filename = 'lena.jpg'
img_codec = cv.IMREAD_COLOR
if argv:
filename = sys.argv[1]
if len(argv) >= 2 and sys.argv[2] == "G":
img_codec = cv.IMREAD_GRAYSCALE
src = cv.imread(cv.samples.findFile(filename), img_codec)

if src is None:
print("无法打开图片 [" + filename + "]")
print("使用方法:")
print("mat_mask_operations.py [图片地址 -- 默认 lena.jpg] [G -- 灰度]")
return -1

cv.namedWindow("Input", cv.WINDOW_AUTOSIZE)
cv.namedWindow("Output", cv.WINDOW_AUTOSIZE)
cv.imshow("Input", src)
t = round(time.time())
dst0 = sharpen(src)
t = (time.time() - t)
print("手写函数耗时秒数: %s" % t)
cv.imshow("Output", dst0)
cv.waitKey()
t = time.time()

kernel = np.array([[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]], np.float32) # kernel 应该是浮点类型

dst1 = cv.filter2D(src, -1, kernel)

t = (time.time() - t)
print("内置 filter2D 函数耗时秒数: %s" % t)
cv.imshow("Output", dst1)
cv.waitKey(0)
cv.destroyAllWindows()
return 0


if __name__ == "__main__":
main(sys.argv[1:])

 

基本方法

 

现在让我们看看如何通过使用基本的像素访问方法或使用 filter2D() 函数来实现这一点。

 

下面是一个实现此功能的函数:

 

def is_grayscale(my_image):
return len(my_image.shape) < 3
def saturated(sum_value):
if sum_value > 255:
sum_value = 255
if sum_value < 0:
sum_value = 0
return sum_value
def sharpen(my_image):
if is_grayscale(my_image):
height, width = my_image.shape
else:
my_image = cv.cvtColor(my_image, cv.CV_8U)
height, width, n_channels = my_image.shape
result = np.zeros(my_image.shape, my_image.dtype)

for j in range(1, height - 1):
for i in range(1, width - 1):
if is_grayscale(my_image):
sum_value = 5 * my_image[j, i] - my_image[j + 1, i] - my_image[j - 1, i] \
- my_image[j, i + 1] - my_image[j, i - 1]
result[j, i] = saturated(sum_value)
else:
for k in range(0, n_channels):
sum_value = 5 * my_image[j, i, k] - my_image[j + 1, i, k] \
- my_image[j - 1, i, k] - my_image[j, i + 1, k]\
- my_image[j, i - 1, k]
result[j, i, k] = saturated(sum_value)

return result

 

首先,我们确保输入的图像数据为无符号8位格式。

 

my_image = cv.cvtColor(my_image, cv.CV_8U)

 

我们创建一个与我们的输入具有相同大小和相同类型的输出图像。根据通道的数量,我们可以有一个或多个子列。

 

height, width, n_channels = my_image.shape
result = np.zeros(my_image.shape, my_image.dtype)

 

我们需要访问多个行和列,这可以通过在当前中心 (i,j) 上加或减 1 来完成。然后我们应用这个和,将新值放入 result 矩阵中。

 

filter2D 函数

 

在图像处理中,应用这样的过滤器是如此的常见,以至于在 OpenCV 中有一个函数会负责应用遮罩(在某些地方也称为内核)。为此,你首先需要定义一个保存掩码的对象:

kernel = np.array([[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]], np.float32)

  

然后调用 filter2D() 函数指定要使用的输入、输出图像和内核:

 

dst1 = cv.filter2D(src, -1, kernel)

 

这个函数更短,更简洁,而且由于进行了一些优化,它通常比手工编码的方法更快。

 

 

 

 

 

官方文档:

https://docs.opencv.org/4.x/d7/d37/tutorial_mat_mask_operations.html

文章转载自数据库杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论