图像处理100问(1~5)

大兔子大兔子 提交于 2020-03-05 14:55:55

小记:

问题1 — RGB与BGR转换
问题2 — BGR灰度化
问题3 — 二值化
问题4 — 大津二值化算法
问题5 — RGB转HSV
一方面是考察图像的以上原理,一方面是考察numpy的使用。

参考: numpy库的基本使用

问题一:通道交换

读取图像,然后将RGB\text{RGB}通道替换成BGR\text{BGR}通道。

下面的代码用于提取图像的红色通道。

解析:

要把蓝色部分变成红色,而图中蓝色明显,说明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部分的差别越大,故以此分割。

算法实现:

前景的像素点数为N0N_0,占整幅图像的比例为ω0ω_0,其平均灰度μ0μ_0;

背景的像素点数为N1N_1,占整幅图像的比例为ω0\omega_0,其平均灰度为μ1μ_1

图像的总平均 灰度记为μ, μ=ω0μ0+ω1μ1\omega_0*μ_0+\omega_1*μ_1

类间方差$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公式,这是这个博客给的公式,但是原答案不是用这个公式

img
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()   #但是显示出来的图像不一样,不知道为什么

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!