在本⽂中,我们将学习如何使⽤ NumPy 对图像进⾏⼆值化,当然,我们将使⽤ OpenCV 来读取灰度和 RGB 格式的图像。 要理解⼆进制是什么ーー⼆进制是由两种东西组成的东西。在计算机术语中,⼆进制只是0和1。如果我们要把同样的事情在图像中联系起来,那么就是说⿊⽩图像中:
0 表⽰⿊⾊
1 表⽰⽩⾊
在学习图像处理的初始阶段,我们通常认为灰度图像是⼀个⼆值图像。虽然不是。但是慢慢地,当我们开始谈论这个话题时,我们意识到我们错得有多离谱。因此,接下来,我们将学习如何使⽤库和不使⽤库(NumPy ⽤于矩阵操作,只是为了避免使⽤规则 for 循环时程序速度缓慢)将图像进⾏⼆进制化。除此之外,我们还将利⽤ Matplotlib 来绘制结果。 RGB 和灰度概述
对于灰度图像来说,⼆值化运算的效果⾮常好。彩⾊(RGB)图像的问题在于,每个像素都是⼀个⽮量,代表3个唯⼀的值,⼀个是红⾊,⼀个是绿⾊,⼀个是蓝⾊。 ⼀个典型的灰度图像的矩阵看起来像:
array([[162, 162, 162, ..., 170, 155, 128],
[162, 162, 162, ..., 170, 155, 128],
GRAPHICALABSTRACT
[162, 162, 162, ..., 170, 155, 128],
...,
[ 43, 43, 50, ..., 104, 100, 98],
[ 44, 44, 55, ..., 104, 105, 108],
[ 44, 44, 55, ..., 104, 105, 108]], dtype=uint8)
⼀个典型的 RGB 图像的矩阵看起来像:
array([[[226, 137, 125], ..., [200, 99, 90]],
[[226, 137, 125], ..., [200, 99, 90]],
吕剧王定保借当
[[226, 137, 125], ..., [200, 99, 90]],
...,
[[ 84, 18, 60], ..., [177, 62, 79]],
[[ 82, 22, 57], ..., [185, 74, 81]],
[[ 82, 22, 57], ..., [185, 74, 81]]], dtype=uint8)
如果我们将 R,G 和 B 三个通道的像素从上⾯的矩阵中分离出来,我们得到。
R 矩阵
array([[226, 226, 223, ..., 230, 221, 200],
[226, 226, 223, ..., 230, 221, 200],
政协提案[226, 226, 223, ..., 230, 221, 200],
...,
心脏麻痹
[ 84, 84, 92, ..., 173, 172, 177],
[ 82, 82, 96, ..., 179, 181, 185],
[ 82, 82, 96, ..., 179, 181, 185]], dtype=uint8)
G 矩阵
array([[137, 137, 137, ..., 148, 130, 99],
[137, 137, 137, ..., 148, 130, 99],
[137, 137, 137, ..., 148, 130, 99],
...,
[ 18, 18, 27, ..., 73, 68, 62],
[ 22, 22, 32, ..., 70, 71, 74],
[ 22, 22, 32, ..., 70, 71, 74]], dtype=uint8)
B 矩阵
array([[125, 125, 133, ..., 122, 110, 90],
[125, 125, 133, ..., 122, 110, 90],
[125, 125, 133, ..., 122, 110, 90],
...,
[ 60, 60, 58, ..., 84, 76, 79],
[ 57, 57, 62, ..., 79, 81, 81],
[ 57, 57, 62, ..., 79, 81, 81]], dtype=uint8)
⽆论我们对灰度图像进⾏什么操作,我们都需要对 RGB 图像进⾏相同的计算,但需要将 R,G 和 B 通道分离3次,最后将它们合并为⼀个正确的 RGB 图像。
编程时间
亚太经济我们主要使⽤的软件库是:
NumPy
Matplotlib
OpenCV
导⼊软件库
import numpy as np
import cv2
import json
from matplotlib import pyplot as plt
读取图⽚
def read_this(image_file, gray_scale=False):
image_src = cv2.imread(image_file)
if gray_scale:
image_src = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY)
else:
image_src = cv2.cvtColor(image_src, cv2.COLOR_BGR2RGB)
return image_src
上⾯的函数以灰度或者 RGB 的形式读取图像并返回图像矩阵。 实现代码
为了将图像转换为⼆值图像,我们可以简单地利⽤ cv2库中提供的threshold()⽅法。这种⽅法,不管图像是什么(灰度或 RGB)转换成⼆进制。使⽤时需要4个参数。
src:基本上就是图像矩阵
thresh:阈值,基于这个阈值像素被赋予⼀个新的值。如果像素⼩于这个值,我们将把这些像素重新赋值为255;否则,像素将重新定值为0
maxval:图像可以包含的最⼤像素值(255)
type:⼀种给定的阈值类型,并基于该类型计算操作。
在此之后,我们将在下⾯的函数绘制结果以查看变化。
def binarize_lib(image_file, thresh_val=127, with_plot=False, gray_scale=False):
image_src = read_this(image_file=image_file, gray_scale=gray_scale)
th, image_b = cv2.threshold(src=image_src, thresh=thresh_val, maxval=255, type=cv2.THRESH_BINARY) if with_plot:
cmap_val = None if not gray_scale else 'gray'
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(10, 20))
ax1.axis("off")
ax1.title.set_text('Original')
ax2.axis("off")
ax2.title.set_text("Binarized")
ax1.imshow(image_src, cmap=cmap_val)
ax2.imshow(image_b, cmap=cmap_val)
return True
return image_b
让我们测试⼀下上⾯的函数:
binarize_lib(image_file='lena_original.png', with_plot=True)
binarize_lib(image_file='lena_original.png', with_plot=True, gray_scale=True)
现在我们已经看到了原始图像和⼆进制图像的结果,很明显,使⽤库中提供的函数编写的代码对这两者都适⽤。是时候让我们从头开始编写如何使⽤ NumPy 对图像进⾏⼆值化。
从零开始的代码实现
⾸先,我们将编写⼀个函数,将⼩于指定阈值的像素值重新赋值为255。
通过这样做,我们可以看到下⾯这样的东西:
def convert_binary(image_matrix, thresh_val):
white = 255
black = 0
initial_conv = np.where((image_matrix <= thresh_val), image_matrix, white)
final_conv = np.where((initial_conv > thresh_val), initial_conv, black)
return final_conv
集里中学
我们将上⾯的函数通过分离 r、 g 和 b 值进⾏三次调⽤,最后将它们合并得到⼆值化图像。⼀旦这样做,我们就可以像以前那样绘制结果。