小记:
问题1 — RGB与BGR转换
问题2 — BGR灰度化
问题3 — 二值化
问题4 — 大津二值化算法
问题5 — RGB转HSV
一方面是考察图像的以上原理,一方面是考察numpy的使用。
参考: numpy库的基本使用
问题一:通道交换
读取图像,然后将通道替换成通道。
下面的代码用于提取图像的红色通道。
解析:
要把蓝色部分变成红色,而图中蓝色明显,说明B通道灰度值小,故而可以交换 B和R通道中的数值,这样B通道灰度值大,颜色变浅,B通道的灰度值变小,颜色变深,红色也就显现出来了。
import cv2
def BGR2RGB(img):
b=img[:,:,0].copy()
g=img[:,:,1]
r=img[:,:,2]
img[:,:,0]=r
img[:,:,1]=g
img[:,:,2]=b
return img
img=cv2.imread("imori.jpg")
img=BGR2RGB(img)
cv2.imshow("result",img)
cv2.waitKey()
问题二:灰度化(Grayscale)
import cv2
import numpy as np
def BGR2GRAY(img):
b=img[:,:,0].copy()
g=img[:,:,1]
r=img[:,:,2]
out = 0.2126 * r + 0.7152 * g + 0.0722 * b
out=out.astype(np.uint8) #数据类型转换
cv2.imshow("gray1",out)
img=cv2.imread("imori.jpg")
BGR2GRAY(img) //自己写函数
gray2=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) //库里的
cv2.imshow("gray2",gray2)
cv2.waitKey()
问题三:二值化(Thresholding)
import cv2
import numpy as np
def Thresholding():
w,h =img1.shape
for a in range(w):
for b in range (h):
img1[a][b]=255 if img1[a][b]>=128 else 0
cv2.imshow("dst1",img1)
def binarization():
#这个是numpy的特性,在list中不能使用
img3[img3<128]=0
img3[img3>=128]=255
cv2.imshow("dst3",img3)
if __name__=='__main__':
img=cv2.imread("imori.jpg",0)
img1=img.copy()
img2=img.copy()
img3=img.copy()
#朴素写法
Thresholding()
#使用numpy的特性写的
binarization()
#用库函数
t,img2=cv2.threshold(img2,128,255,cv2.THRESH_BINARY)
cv2.imshow("dst2",img2)
cv2.waitKey()
问题四:大津二值化算法(Otsu’s Method)
原理: 传送门
最大类间方差算法
将图像分成背景和目标2部分。背景和目标之间的类间方差
越大,说明构成图像的2部分的差别越大,故以此分割。
算法实现:
前景的像素点数为,占整幅图像的比例为,其平均灰度;
背景的像素点数为,占整幅图像的比例为,其平均灰度为。
图像的总平均 灰度记为μ, μ=
类间方差$g=ω_0(μ_0-μ)2+ω_1(μ_1-μ)2=ω_0ω_1(μ_0-μ_1)^2 $
有了这个之后,就用遍历得到使g最大的阈值T
import cv2
import numpy as np
import matplotlib.pyplot as plt
#原图
img1=cv2.imread("5.jpeg",0)
#otsu处理
t2,img2=cv2.threshold(img1,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
#合并图片显示
img=np.hstack([img1,img2])
name="1:img 2:otsu("+str(t2)+")"
cv2.imshow(name,img)
cv2.waitKey()
问题五:HSV变换
RGB转HSV公式,这是这个博客给的公式,但是原答案不是用这个公式
import cv2
import numpy as np
def BGR2HSV(_img):
img=_img.copy()/255
hsv=np.zeros_like(img,dtype=np.float32)
# 得到以层为轴的最大和最小值
max_v= np.max(img,axis=2).copy()
min_v= np.min(img,axis=2).copy()
# 得到以层为轴的最大值的下标(即所在层)
max_arg=np.argmax(img,axis=2)
#HSV图像的3层分别为H,S,V
#对于H层 ,用角度度量,取值范围为0°~360°
hsv[..., 0][np.where(max_v == min_v)] = 0
ind=np.where(max_arg==0) #最大值在bgr的b层的
hsv[..., 0][ind] = 60 * (img[...,2][ind]-img[...,1][ind])/(max_v[ind]-min_v[ind])+240
ind=np.where(max_arg==1) #最大值在bgr的g层的
hsv[..., 0][ind] = 60 * (img[...,0][ind]-img[...,2][ind])/(max_v[ind]-min_v[ind])+120
ind=np.where(max_arg==2) #最大值在bgr的r层的
hsv[..., 0][ind] = 60 * (img[...,1][ind]-img[...,0][ind])/(max_v[ind]-min_v[ind])+0
# 对于S层 表示 颜色接近光谱色的程度
hsv[...,1][np.where(max_v==0)]=0
ind=np.where(max_v!=0)
hsv[...,1][ind]=(max_v[ind]-min_v[ind])/max_v[ind]
# 对于V层 表示颜色明亮的程度
hsv[...,2]=max_v.copy()
return hsv
def BGR2HSV22(_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
img=cv2.imread("imori.jpg")
hsv22=BGR2HSV22(img) #这个是用答案的,最小值
hsv=BGR2HSV(img) # 看那个博客的公式,用最大值的
cv2.imshow("hsv",hsv)
cv2.imshow("hsv22",hsv22)
cv2.waitKey() #但是显示出来的图像不一样,不知道为什么
来源:CSDN
作者:Mally-CJ
链接:https://blog.csdn.net/qq_43235540/article/details/104672890