起始
opencv与matplotlib默认显示图片通道顺序不同,opencv为典型的BGR通道,而matplotlib用的则为我们熟知的RGB通道
- 导包阶段
#一般开始可以直接将这三个包直接导入,以免后续麻烦
import cv2
import numpy as np
from matplotlib import pyplot as plt
- 读取图像
img=cv2.imread('123.jpg',0)#后面这个0默认以灰度方式读入,为1时读入原图像
- 展示图像
#opencv展示图像方法
cv2.imshow('image',img)#这里打开的窗口是不能放大和缩小的,如果需要放大或缩小,请在前面把窗口自定义命名。cv2.namedWindow('image',cv2.WINDOW_NORMAL)
cv2.waitKey(0)#这里的目的保证按esc键退出,即关闭图像
cv2.destroyAllWindows()
#matplotlib用法,这里img要做控件变换,否则看起来图像颜色非常不对
plt.imshow(img,cmap='gray',interpolation='bicubic')
plt.xticks([]),plt.yticks([])
plt.show()
- 保存图像
cv2.imwrite('123.png',img)
- 颜色控件转换,即使得BGR通道顺序更改为RGB通道顺序
#img实质为一个三维数组,
#len(img)一般代表行的数量(图像高度)
#len(img[0])一般代表列得数量(图像宽度)
#len(img[0][0])一般代表图像深度
#img[0][0]即为像素点的实际内容,灰度一般为0-255的数值,彩色图像一般为[77,89,56]这样的数组
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
- 彩色图像转灰度
def BGR2GRAY(img):
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# Gray scale,设置为uint8类型是必须的,防止报错
# 也可以用out=np.array(out,dtype=uint8)来表示
out = 0.2126 * r + 0.7152 * g + 0.0722 * b
out = out.astype(np.uint8)
return out
7.固定阈值转灰度
#这种运算可以简便地实现,得益于np数据格式的优势
def binarization(img, th=128):
img[img < th] = 0
img[img >= th] = 255
return img
- 大津二值化算法即Otsu's二值化
原理
Otsu 算法的原理非常简单,算法假定该图像根据双模直方图(前景像素和背景像素)把包含两类像素,于是它要计算能将两类分开的最佳阈值,使得它们的类内方差最小;由于两两平方距离恒定,所以即它们的类间方差最大。
具体公式详细推导
最后得到Sb2=0
1(M0-M1)2
-
0
1被阈值t分开的两个类中的像素数占总像素数的比率满足
0+
1=1
- M0与 M1是这两个类的像素值的平均值,算法主要遍历0-255,求解Sb2的最大值时所取得的阈值
#返回值为大津算法得到的最佳分割阈值
def OTSU_enhance(img_gray, th_begin=0, th_end=256, th_step=1):
assert img_gray.ndim == 2, "must input a gary_img"
max_g = 0
suitable_th = 0
for threshold in range(th_begin, th_end, th_step):
bin_img = img_gray > threshold
bin_img_inv = img_gray <= threshold
fore_pix = np.sum(bin_img)
back_pix = np.sum(bin_img_inv)
if 0 == fore_pix:
break
if 0 == back_pix:
continue
w0 = float(fore_pix) / img_gray.size
u0 = float(np.sum(img_gray * bin_img)) / fore_pix
w1 = float(back_pix) / img_gray.size
u1 = float(np.sum(img_gray * bin_img_inv)) / back_pix
# intra-class variance
g = w0 * w1 * (u0 - u1) * (u0 - u1)
if g > max_g:
max_g = g
suitable_th = threshold
return suitable_th
- 减色处理
#将值固定在32、96、160、224这四个值上面,完成减色的目的
def dicrease_color(img):
out = img.copy()
out = out // 64 * 64 + 32
return out
- BGR与HSV相互转化
def BGR2HSV(_img):
img = _img.copy() / 255.
hsv = np.zeros_like(img, dtype=np.float32)
# get max and min
max_v = np.max(img, axis=2).copy()
min_v = np.min(img, axis=2).copy()
min_arg = np.argmin(img, axis=2)
# H
hsv[..., 0][np.where(max_v == min_v)]= 0
## if min == B
ind = np.where(min_arg == 0)
hsv[..., 0][ind] = 60 * (img[..., 1][ind] - img[..., 2][ind]) / (max_v[ind] - min_v[ind]) + 60
## if min == R
ind = np.where(min_arg == 2)
hsv[..., 0][ind] = 60 * (img[..., 0][ind] - img[..., 1][ind]) / (max_v[ind] - min_v[ind]) + 180
## if min == G
ind = np.where(min_arg == 1)
hsv[..., 0][ind] = 60 * (img[..., 2][ind] - img[..., 0][ind]) / (max_v[ind] - min_v[ind]) + 300
# S
hsv[..., 1] = max_v.copy() - min_v.copy()
# V
hsv[..., 2] = max_v.copy()
return hsv
def HSV2BGR(_img, hsv):
img = _img.copy() / 255.
# get max and min
max_v = np.max(img, axis=2).copy()
min_v = np.min(img, axis=2).copy()
out = np.zeros_like(img)
H = hsv[..., 0]
S = hsv[..., 1]
V = hsv[..., 2]
C = S
H_ = H / 60.
X = C * (1 - np.abs( H_ % 2 - 1))
Z = np.zeros_like(H)
vals = [[Z,X,C], [Z,C,X], [X,C,Z], [C,X,Z], [C,Z,X], [X,Z,C]]
for i in range(6):
ind = np.where((i <= H_) & (H_ < (i+1)))
out[..., 0][ind] = (V - C)[ind] + vals[i][0][ind]
out[..., 1][ind] = (V - C)[ind] + vals[i][1][ind]
out[..., 2][ind] = (V - C)[ind] + vals[i][2][ind]
out[np.where(max_v == min_v)] = 0
out = np.clip(out, 0, 1)
out = (out * 255).astype(np.uint8)
return out
- 平均池化
#相当于打马赛克
def average_pooling(img, G=8):
out = img.copy()
H, W, C = img.shape
Nh = int(H / G)
Nw = int(W / G)
for y in range(Nh):
for x in range(Nw):
for c in range(C):
out[G*y:G*(y+1), G*x:G*(x+1), c] = np.mean(out[G*y:G*(y+1), G*x:G*(x+1), c]).astype(np.int)
return out
- 最大池化
def max_pooling(img, G=8):
# Max Pooling
out = img.copy()
H, W, C = img.shape
Nh = int(H / G)
Nw = int(W / G)
for y in range(Nh):
for x in range(Nw):
for c in range(C):
out[G*y:G*(y+1), G*x:G*(x+1), c] = np.max(out[G*y:G*(y+1), G*x:G*(x+1), c])
return out
网友评论