题来自于
读取图片:「画像処理100本ノック」中文版本!为图像处理初学者设计的 100 个问题。
读取图像,然后将通道替换成通道。
下面的代码用于提取图像的红色通道。
注意,cv2.imread() 的系数是按顺序排列的!
其中的变量red表示的是仅有原图像红通道的imori.jpg。
答案:
import cv2
# function: BGR -> RGB
def BGR2RGB(img):
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# RGB > BGR
img[:, :, 0] = r
img[:, :, 1] = g
img[:, :, 2] = b
return img
# Read image
img = cv2.imread("imori.jpg")
# BGR -> RGB
img = BGR2RGB(img)
# Save result
cv2.imwrite("out.jpg", img)
cv2.imshow("result", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
问题二:灰度化(Grayscale)
将图像灰度化吧!
灰度是一种图像亮度的表示方法,通过下式计算: Y = 0.2126 R + 0.7152 G + 0.0722 B Y = 0.2126 R + 0.7152 G + 0.0722 B Y=0.2126 R+0.7152 G+0.0722 B
import cv2
import numpy as np
# Gray scale
def BGR2GRAY(img):
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# Gray scale
out = 0.2126 * r + 0.7152 * g + 0.0722 * b
out = out.astype(np.uint8)
return out
# Read image
img = cv2.imread("imori.jpg").astype(np.float)
# Grayscale
out = BGR2GRAY(img)
# Save result
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
问题三:二值化(Thresholding)
二值化是将图像使用黑和白两种颜色表示的方法。
先进行灰度化,然后以阈值为界限,大于阈值的=255,小于阈值的=0。
我们将灰度的阈值设置为128来进行二值化,即:
if (x>=128)x=255
else x=0
import cv2
import numpy as np
# Gray scale
def BGR2GRAY(img):
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# Gray scale
out = 0.2126 * r + 0.7152 * g + 0.0722 * b
out = out.astype(np.uint8)
return out
# binalization
def binarization(img, th=128):
img[img < th] = 0
img[img >= th] = 255
return img
# Read image
img = cv2.imread("imori.jpg").astype(np.float32)
# Grayscale
out = BGR2GRAY(img)
# Binarization
out = binarization(out)
# Save result
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
问题四:大津二值化算法(Otsu’s Method)
简介
我们在最灰度图做二值化时,需要设定一个分割阈值,我们并没有一个万能的阈值。而Otsu大津算法则是根据灰度图本身的信息,自动确定最佳阈值,实现以最佳阈值对灰度图进行二值化。
需要注意的是,大津算法并不是直接进行二值化处理,而是得到一个整型数字,也即阈值,我们得到阈值再进行二值化。
一般情况下,我们将我们感兴趣的部分称为前景,对于不感兴趣的称为背景。
大津算法的思想是比较简单的,我们认为分为的前景和背景之间差异是较大的,而前景部分中的像素是相似的,背景部分中的像素是相似的:同一类中差异小,不同类中差异大。那么如果存在一个阈值,使得图像分为了前景和背景,应当符合同一类中差异最小,不同类中差异最大,这个值就是最佳阈值。根据这个最佳阈值分割的图像效果应当是最好的(即将前景和背景彻底分割开)。
那么所谓的“差异”如何表示?其实就是用方差来表示:如果单个的数据其越偏离于中心,那么,其方差值也就越大。如果同一类中方差越小,那么表示同一类中差异也小;不同类之间方差越大,表示不同类中差异越大。
题使用大津算法来二值化图像吧。
大津算法,也被称作最大类间方差法,是一种可以自动确定二值化中阈值的算法。
从类内方差和类间方差的比值计算得来:
import cv2
import numpy as np
# Gray scale
def BGR2GRAY(img):
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# Gray scale
out = 0.2126 * r + 0.7152 * g + 0.0722 * b
out = out.astype(np.uint8)
return out
# Otsu Binarization
def otsu_binarization(img, th=128):
max_sigma = 0
max_t = 0
# determine threshold
for _t in range(1, 255):
v0 = out[np.where(out < _t)]
m0 = np.mean(v0) if len(v0) > 0 else 0.
w0 = len(v0) / (H * W)
v1 = out[np.where(out >= _t)]
m1 = np.mean(v1) if len(v1) > 0 else 0.
w1 = len(v1) / (H * W)
sigma = w0 * w1 * ((m0 - m1) ** 2)
if sigma > max_sigma:
max_sigma = sigma
max_t = _t
# Binarization
print("threshold >>", max_t)
th = max_t
out[out < th] = 0
out[out >= th] = 255
return out
# Read image
img = cv2.imread("imori.jpg").astype(np.float32)
H, W, C =img.shape
# Grayscale
out = BGR2GRAY(img)
# Otsu's binarization
out = otsu_binarization(out)
# Save result
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()



