網(wǎng)頁(yè)設(shè)計(jì)與網(wǎng)站建設(shè)的理解link友情買(mǎi)賣(mài)
半色調(diào)技術(shù)
半色調(diào)技術(shù)是一種將灰度圖像轉(zhuǎn)換為黑白圖像的技術(shù)。它是通過(guò)將灰度圖像的像素值映射到黑白像素值上來(lái)實(shí)現(xiàn)的。
比如說(shuō),在一塊只能顯示純黑或純白的屏幕上,如何將一張灰度圖顯示出灰度的效果,這時(shí)就可以用半色調(diào)技術(shù)實(shí)現(xiàn)。
如下,左邊是一張灰度圖,中間是使用半色調(diào)技術(shù)轉(zhuǎn)換后輸出的圖像,右邊是輸出圖像的局部放大
初始灰度圖 | 半色調(diào)轉(zhuǎn)換后的輸出圖像 | 輸出圖像局部放大(使用win10自帶【畫(huà)圖】軟件打開(kāi)放大) |
---|---|---|
![]() | ![]() | ![]() |
原理
基本原理
我們都知道,一個(gè)像素點(diǎn)有0~255共256種灰度值,值越大圖像越“白”,反之越“黑”。
對(duì)于一些屏幕,只能顯示0或1(用1表示255)兩種灰度值,也就是只能顯示純黑或純白,這怎么辦?
半色調(diào)技術(shù)實(shí)際是把一個(gè)像素點(diǎn)用一個(gè)矩陣塊來(lái)表示,如果像素值比較大(越白),那么矩陣快白色部分就越多,如圖所示:
這個(gè)矩陣就是bayer矩陣,矩陣邊長(zhǎng)可以選擇1,2,4,8,16,上圖矩陣邊長(zhǎng)是2
如果是16,那么就可以表示16*16=256種灰度值了
如上圖所示,對(duì)于邊長(zhǎng)為2的bayer矩陣,假如只有4種顏色值(0,1,2,3),如果像素值比0大,那么就把bayer矩陣的位置0設(shè)置為白色;如果比1大,就把位置0和1都設(shè)置為白色……
但實(shí)際上,灰度值有256種,因此bayer矩陣需要乘以(256/(2*2)),如下
如果像素值比128大,那么0,64,128這3個(gè)位置都設(shè)置為白色
可以看出,假設(shè)輸入圖像邊長(zhǎng)為a,bayer矩陣邊長(zhǎng)為k,則輸出圖像的邊長(zhǎng)為a*k,即是輸入圖像的k倍
bayer矩陣生成
注意:整數(shù)*矩陣即矩陣的數(shù)乘運(yùn)算,相當(dāng)于矩陣每個(gè)元素都乘以一個(gè)整數(shù)
根據(jù)這個(gè)公式,可以寫(xiě)出一個(gè)代碼:
def getStandardMat(k):'''函數(shù)作用:獲取bayer矩陣return:是否生成成功,成功的話(huà)同時(shí)返回numpy類(lèi)型的矩陣k: 是bayer矩陣的階數(shù),取值一般為1 2 4 8 16'''if k & (k-1) != 0:return False, Noneif k == 1:return True, [[0.5]]m = [[0, 2], [3, 1]]m = np.array(m)while(m.shape[0] != k):m1 = np.zeros((m.shape[0]*2, m.shape[1]*2))m1[:m.shape[0], :m.shape[1]] += 4*mm1[:m.shape[0], m.shape[1]:] += 4*m+2m1[m.shape[0]:, :m.shape[1]] += 4*m+3m1[m.shape[0]:, m.shape[1]:] += 4*m+1m = m1return True, m
測(cè)試一下:
![]() | ![]() | ![]() |
---|
實(shí)踐操作
該程序?qū)崿F(xiàn)讀取一張RGB圖片,轉(zhuǎn)為灰度圖后再采用變色調(diào)技術(shù)轉(zhuǎn)換圖片
使用該程序只需要修改輸入圖片路徑以及輸出圖片路徑即可
# 該文件實(shí)現(xiàn)半色調(diào)技術(shù)的代碼import cv2
import numpy as npdef getBayerMat(k):'''函數(shù)作用:獲取bayer矩陣return:是否生成成功,成功的話(huà)同時(shí)返回numpy類(lèi)型的矩陣k: 是bayer矩陣的階數(shù),取值一般為1 2 4 8 16'''if k & (k-1) != 0:return False, Noneif k == 1:return True, np.array([[0.5]])m = [[0, 2], [3, 1]]m = np.array(m)while(m.shape[0] != k):m1 = np.zeros((m.shape[0]*2, m.shape[1]*2))m1[:m.shape[0], :m.shape[1]] += 4*mm1[:m.shape[0], m.shape[1]:] += 4*m+2m1[m.shape[0]:, :m.shape[1]] += 4*m+3m1[m.shape[0]:, m.shape[1]:] += 4*m+1m = m1return True, mdef convertImg(img, k=4, f=False, useGray=False):'''k:bayer矩陣大小f:由于轉(zhuǎn)換后圖像尺寸會(huì)變大k倍,f表示是否先縮小k倍useGray:傳入的img是否為灰度圖'''if not useGray:img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)if f:img = cv2.resize(img, dsize=None, fx=1/k, fy=1/k)ret, bayers = getBayerMat(k)if not ret:print(f"矩陣階數(shù)k={k}非2的倍數(shù)")returnbayers *= (256//(k*k))h, w = img.shapenewImg = np.zeros((k*h, k*w), dtype='uint8')# 遍歷圖像每個(gè)像素點(diǎn)for i in range(0, h, 1):for j in range(0, w, 1):# 對(duì)于每個(gè)像素點(diǎn),遍歷bayer矩陣,判斷是否該把矩陣中某一位置設(shè)置為純白(255)或純黑(0)for p in range(k): for q in range(k):if img[i][j] > bayers[p][q]:newImg[k*(i)+p][k*(j)+q] = 255else:newImg[k*(i)+p][k*(j)+q] = 0return newImgif __name__ == '__main__':imgPath = r'D:\Users\xxx\Desktop\imgs\1-1.jpg'img = cv2.imread(imgPath, 0) # 讀取圖片并轉(zhuǎn)為灰度圖nimg = convertImg(img, k=4, f=False, useGray=True)cv2.imwrite("../out/b2.png", nimg) # 輸出轉(zhuǎn)換后的圖片
使用pyqt5做一個(gè)GUI操作界面
?代碼下載
需要安裝的庫(kù)
PyQt5 5.15.0
opencv-python 4.3.0.36
numpy 1.19.0
使用方法:
運(yùn)行src/main.py文件即可
> python main.py