EE103(2):圖像線性處理

不使用opencv的庫函數(shù),完全運(yùn)用numpy和線性代數(shù)知識,我們能在多大程度上處理圖像呢

多通道轉(zhuǎn)單通道

  • 可以使用(r,g,b)=(1/3,1/3,1/3)來轉(zhuǎn)換
  • 也可以使用(r,g,b)=(0.299,0.587,0.114)來轉(zhuǎn)換

原圖(pixiv id:490219):

在這里插入圖片描述

兩種轉(zhuǎn)換方式結(jié)果對比

在這里插入圖片描述

亮度、對比度

y=ax+[(1-a)avg(x)+b]·1

  • x為像素矩陣
  • 1為全1矩陣
  • a越大,對比度越高
  • b越大亮度越高

不同的a(0、0.4、0.8、1.2、1.6、2)情況下圖像的情況(不同b情況下略):

在這里插入圖片描述

變換

  • 水平縮放:對于m*n的原圖像,右乘k*m的矩陣A可以水平縮放為k*n的圖像。其中,A的縱列代表了縮放過程中對原圖像橫排每個(gè)像素的加權(quán)A的橫行代表了最終圖像橫排每個(gè)位的生成原圖像的縱列代表了最終圖像縱列每個(gè)位的生成。在縮放過程中,最終圖像橫排每個(gè)位的生成次數(shù)應(yīng)該和原圖像不同,并且每次生成時(shí)應(yīng)該對原圖像橫排不同像素進(jìn)行加權(quán)

    • 臨近插值放大一倍的矩陣A:\left[\begin{matrix} 1&1&0&0&...&0&0\\0&0&1&1&...&0&0\\0&0&0&0&...&0&0\\\vdots\\0&0&0&0&...&1&1\end{matrix}\right]
    • 線性插值放大一倍的矩陣A:\left[\begin{matrix} 1&0.5&0&0&...&0&0\\0&0.5&1&0.5&...&0&0\\0&0&0&0.5&...&0&0\\\vdots\\0&0&0&0&...&0.5&1\end{matrix}\right]
  • 垂直縮放:對于m*n的原圖像,左乘n*k的矩陣A可以垂直縮放為m*k的圖像。其中,A的橫行代表了縮放過程中對原圖像縱列每個(gè)像素的加權(quán),A的縱列代表了最終圖像縱列每個(gè)位的生成,原圖像的橫行代表了最終圖像橫行每個(gè)位的生成。在縮放過程中,最終圖像縱列每個(gè)位的生成次數(shù)應(yīng)該和原圖像不同,并且每次生成時(shí)應(yīng)該對原圖像縱列不同像素進(jìn)行加權(quán)

    • 臨近插值放大一倍的矩陣A:\left[\begin{matrix} 1&0&0&...&0\\1&0&0&...&0\\0&1&0&...&0\\0&1&0&...&0\\\vdots\\0&0&0&...&1\\0&0&0&...&1\end{matrix}\right]
    • 線性插值放大一倍的矩陣A:\left[\begin{matrix} 1&0&0&...&0\\0.5&0.5&0&...&0\\0&1&0&...&0\\0&0.5&0.5&...&0\\\vdots\\0&0&0&...&0.5\\0&0&0&...&1\end{matrix}\right]
  • 旋轉(zhuǎn)、翻轉(zhuǎn):矩陣旋轉(zhuǎn)與轉(zhuǎn)置

  • 偏移:切片與連接

常用圖層混合模式

設(shè)像素矩陣x位于像素矩陣y之上且范圍比y小,坐標(biāo)i,j\in x坐標(biāo)范圍

  • 正常:y_{ij}=x_{ij}

  • 變暗系

    • 變暗:y_{ij}=min\{y_{ij},x_{ij}\},分通道比較替換
    • 正片疊底:y_{ij}=y_{ij}*x_{ij}/255
    • 顏色加深:y_{ij}=(y_{ij}+x_{ij}-255)*255/x_{ij}
    • 線性加深:y_{ij}=y_{ij}+x_{ij}-255
    • 深色:y_{ij}=min\{y_{ij},x_{ij}\},比較全通道數(shù)值
在這里插入圖片描述
  • 變亮系

    • 變亮:y_{ij}=max\{y_{ij},x_{ij}\},分通道比較替換
    • 濾色:y_{ij}=255-(255-y_{ij})*(255-x_{ij})/255
    • 顏色減淡:y_{ij}=y_{ij}+x_{ij}*y_{ij}/(255-y_{ij})
    • 線性減淡:y_{ij}=y_{ij}+x_{ij}
    • 淺色:y_{ij}=max\{y_{ij},x_{ij}\},比較全通道數(shù)值
在這里插入圖片描述
  • 疊加:根據(jù)y的數(shù)值來決定使用正片疊底還是濾色,盡量保留y的顏色\begin{cases}y_{ij}=x_{ij}*y_{ij}/128\quad y_{ij}\leq128\\y_{ij}=255-(255-x_{ij})*(255-y_{ij})/128\quad y_{ij}>128\end{cases}
在這里插入圖片描述
  • 照射系

    • 柔光:對x數(shù)值高的部分保留較好,\begin{cases}y_{ij}=y_{ij}+(2x_{ij}-255)(y_{ij}-y_{ij}^2/255)/255\quad x_{ij}\leq128\\y_{ij}=y_{ij}+(2x_{ij}-255)(\sqrt{y_{ij}/255}-y_{ij})/255\quad x_{ij}>128\end{cases}
    • 強(qiáng)光:根據(jù)x的數(shù)值來決定使用正片疊底還是濾色,盡量保留x的顏色\begin{cases}y_{ij}=x_{ij}*y_{ij}/128\quad x_{ij}\leq128\\y_{ij}=255-(255-x_{ij})*(255-y_{ij})/128\quad x_{ij}>128\end{cases}
    • 亮光:盡量保留x的顏色,x亮度高時(shí)圖像將被降低對比度并且變亮,x亮度低時(shí)圖像會(huì)被提高對比度并且變暗\begin{cases}y_{ij}=255-(255-y_{ij})/(2*x_{ij})\quad x_{ij}\leq128\\y_{ij}=y_{ij}/(2*(255-x_{ij}))*255\quad x_{ij}>128\end{cases}
    • 線性光:根據(jù)x的數(shù)值來決定使用線性加深還是線性減淡,盡量保留x的顏色y_{ij}=2*x_{ij}+y_{ij}-255
在這里插入圖片描述

模糊

生成一個(gè)M*N的模糊用卷積核x,與原圖像y進(jìn)行卷積運(yùn)算,即y_{ij}=\displaystyle\sum_{m=0}^{M}\sum_{n=0}^{N}x_{mn}y_{i-m,j-n}

結(jié)果的每個(gè)ij位置都相當(dāng)于原圖像ij位置左上M*N范圍內(nèi)的像素加權(quán)和,因此可以實(shí)現(xiàn)模糊

高斯核

生成原理很簡單,對于每個(gè)位置計(jì)算其與右下角橫縱距離,代入二維高斯函數(shù)即可。sigma越大模糊程度越大

def gaussian(u, v, sigma):
    pi = 3.1416
    intensity = 1 / (2.0 * pi * sigma * sigma) * math.exp(- 1 / 2.0 * ((u ** 2) + (v ** 2)) / (sigma ** 2))
    return intensity

def gaussianKernel(r, sigma):
    kernel = np.zeros([r, r])
    for i in range(r):
        for j in range(r):
            kernel[i, j] = gaussian(r-i,r-j, sigma)
    kernel /= np.sum(np.sum(kernel))
    return kernel

運(yùn)動(dòng)模糊核

運(yùn)動(dòng)模糊的原理是一個(gè)方向上的圖像疊加,給出運(yùn)動(dòng)模糊的角度和程度,需要生成一個(gè)權(quán)重和為1的核。對于向右下、左下、右上、左上運(yùn)動(dòng),核分別越靠近左上、右上、左下、右下的權(quán)重最大,其中對角線上r個(gè)格子中有值

設(shè)首項(xiàng)等于公差,解方程1=rd+\frac{r(r-1)}{2}d,得d=\frac{2}{r+r^2}

生成核時(shí),從根據(jù)不同的弧度情況,從左上、右上、左下、右下分別開始向著弧度對應(yīng)的方向?qū)ふ襯個(gè)格并在對應(yīng)點(diǎn)計(jì)算等差數(shù)列對應(yīng)項(xiàng),如果該格已經(jīng)有值,則在其旁邊一格設(shè)置項(xiàng)

def mbkernel(agl,r):
    rad=math.radians(agl)
    w=math.ceil(r*np.abs(np.cos(rad)))
    h=math.ceil(r*np.abs(np.sin(rad)))
    if h==0:
        h+=1
    if w==0:
        w+=1
    d=2/(r+r**2)
    kernel=np.zeros((int(h),int(w)))
    for i in range(0,r):
        if np.sin(rad)>=0:
            y=math.floor(h-i*np.sin(rad)-1)
        else:
            y=math.floor(-i*np.sin(rad))
        if np.cos(rad)>=0:
            x=math.floor(i*np.cos(rad))
        else:
            x=math.floor(w+i*np.cos(rad)-1)
        if kernel[y][x]==0:
            kernel[y][x]=(i+1)*d
        else:
            if np.sin(rad)>=0:
                kernel[y+1][x]=(i+1)*d
            else:
                kernel[y-1][x]=(i+1)*d
    return kernel

卷積

opencv提供了卷積函數(shù)

dst=cv2.filter2D(src,-1,kernel=k,anchor=(-1,-1))    #anchor默認(rèn)位于中間,深度為-1默認(rèn)保持和原圖像相同深度
dst=cv2.filter2D(src,-1,kernel=flip(k),anchor=(k.cols-1,k.rows-1))  #真正意義上的卷積,深度為-1默認(rèn)保持和原圖像相同深度

不使用opencv提供的卷積函數(shù),同樣可以手寫卷積,但運(yùn)行速度極慢

半徑(縱軸)分別為5、15、30下,\sigma(橫軸)分別為10、50、100下高斯模糊的結(jié)果

在這里插入圖片描述

半徑(縱軸)分別為15、50、100下,角度(橫軸)分別為0^o45^o、135^o下運(yùn)動(dòng)模糊的結(jié)果

在這里插入圖片描述

差分

水平差分

對于m*n的原圖像,右乘m*m的矩陣A可以進(jìn)行水平差分。其中,A的縱列代表了縮放過程中對原圖像橫排每個(gè)像素的加權(quán),A的橫行代表了最終圖像橫排每個(gè)位的生成,原圖像的縱列代表了最終圖像縱列每個(gè)位的生成。在差分過程中,最終圖像橫排每個(gè)位的生成次數(shù)應(yīng)該和原圖像相同,并且每次生成時(shí)應(yīng)該對原圖像橫排不同像素進(jìn)行加權(quán)(某個(gè)像素為1,其下一個(gè)像素為-1)

  • 矩陣A:\left[\begin{matrix} 1&0&0&...&0&0\\-1&1&0&...&0&0\\0&-1&1&...&0&0\\\vdots\\0&0&0&...&-1&1\end{matrix}\right]

垂直差分

對于m*n的原圖像,左乘n*n的矩陣A可以進(jìn)行垂直差分。其中,A的橫行代表了縮放過程中對原圖像縱列每個(gè)像素的加權(quán),A的縱列代表了最終圖像縱列每個(gè)位的生成,原圖像的橫行代表了最終圖像橫行每個(gè)位的生成。在縮放過程中,最終圖像縱列每個(gè)位的生成次數(shù)應(yīng)該和原圖像不同,并且每次生成時(shí)應(yīng)該對原圖像縱列不同像素進(jìn)行加權(quán)(某個(gè)像素為1,其下一個(gè)像素為-1)

  • 矩陣A:\left[\begin{matrix} 1&-1&0&...&0\\0&1&-1&...&0\\0&0&1&...&0\\\vdots\\0&0&0&...&-1\\0&0&0&...&1\end{matrix}\right]

圖像復(fù)原

對我們的圖像添加10%椒鹽噪聲

base = cv2.imread("base.jpg",cv2.IMREAD_GRAYSCALE)
noise=np.random.randint(0,100,base.shape)
base=np.where(noise<5,0,base)
base=np.where(noise>=95,255,base)

添加前:

在這里插入圖片描述

添加后:

在這里插入圖片描述

均值濾波

設(shè)半徑為r,均值濾波核是一個(gè)r·r,每個(gè)位置值為\frac{1}{r·r}的方陣

kernel=np.zeros((r,r))
kernel+=1/r/r
在這里插入圖片描述

分別使用半徑為3、5、15的核濾波結(jié)果

中值濾波

設(shè)半徑為r,中值濾波核在圖像上滑動(dòng),每r·r個(gè)位置統(tǒng)計(jì)中值

def med(inputs,R):
    H, W = inputs.shape
    result = np.zeros(inputs.shape)
    H, W = inputs.shape
    for r in range(0, H - R + 1):
        for c in range(0, W - R + 1):
            cur = inputs[r:r + R,c:c + R]
            val = np.median(cur)
            result[r, c] = val
    return result
在這里插入圖片描述

分別使用半徑為3、5、15的核濾波結(jié)果

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容