摘要:本文主要講述如何進行影像量化處理和采樣處理及區域馬賽克特效,
本文分享自華為云社區《[Python影像處理] 二十.影像量化處理和采樣處理及區域馬賽克特效》,作者: eastmount,
本文主要講述如何進行影像量化處理和采樣處理及區域馬賽克特效,
一.影像量化處理
影像通常是自然界景物的客觀反映,并以照片形式或視頻記錄的介質連續保存,獲取影像的目標是從感知的資料中產生數字影像,因此需要把連續的影像資料離散化,轉換為數字化影像,其作業主要包括兩方面——量化和采樣,數字化幅度值稱為量化,數字化坐標值稱為采樣,本章主要講解影像量化和采樣處理的概念,并通過Python和OpenCV實作這些功能,
1.1 概述
所謂量化(Quantization),就是將影像像素點對應亮度的連續變化區間轉換為單個特定值的程序,即將原始灰度影像的空間坐標幅度值離散化,量化等級越多,影像層次越豐富,灰度解析度越高,影像的質量也越好;量化等級越少,影像層次欠豐富,灰度解析度越低,會出現影像輪廓分層的現象,降低了影像的質量,圖6-1是將影像的連續灰度值轉換為0至255的灰度級的程序,
如果量化等級為2,則將使用兩種灰度級表示原始圖片的像素(0-255),灰度值小于128的取0,大于等于128的取128;如果量化等級為4,則將使用四種灰度級表示原始圖片的像素,新影像將分層為四種顏色,0-64區間取0,64-128區間取64,128-192區間取128,192-255區間取192;依次類推,
圖6-2是對比不同量化等級的“Lena”圖,其中(a)的量化等級為256,(b)的量化等級為64,(c)的量化等級為16,(d)的量化等級為8,(e)的量化等級為4,(f)的量化等級為2,
1.2 操作
下面講述Python影像量化處理相關代碼操作,其核心流程是建立一張臨時圖片,接著回圈遍歷原始影像中所有像素點,判斷每個像素點應該屬于的量化等級,最后將臨時影像顯示,下述代碼將灰度影像轉換為兩種量化等級,
# -*- coding: utf-8 -*- import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始影像 img = cv2.imread('lena.png') #獲取影像高度和寬度 height = img.shape[0] width = img.shape[1] #創建一幅影像 new_img = np.zeros((height, width, 3), np.uint8) #影像量化操作 量化等級為2 for i in range(height): for j in range(width): for k in range(3): #對應BGR三分量 if img[i, j][k] < 128: gray = 0 else: gray = 128 new_img[i, j][k] = np.uint8(gray) #顯示影像 cv2.imshow("src", img) cv2.imshow("", new_img) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
其輸出結果如圖6-3所示,它將灰度影像劃分為兩種量化等級,
下面的代碼分別比較了量化等級為2、4、8的量化處理效果,
# -*- coding: utf-8 -*- import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始影像 img = cv2.imread('lena.png') #獲取影像高度和寬度 height = img.shape[0] width = img.shape[1] #創建一幅影像 new_img1 = np.zeros((height, width, 3), np.uint8) new_img2 = np.zeros((height, width, 3), np.uint8) new_img3 = np.zeros((height, width, 3), np.uint8) #影像量化等級為2的量化處理 for i in range(height): for j in range(width): for k in range(3): #對應BGR三分量 if img[i, j][k] < 128: gray = 0 else: gray = 128 new_img1[i, j][k] = np.uint8(gray) #影像量化等級為4的量化處理 for i in range(height): for j in range(width): for k in range(3): #對應BGR三分量 if img[i, j][k] < 64: gray = 0 elif img[i, j][k] < 128: gray = 64 elif img[i, j][k] < 192: gray = 128 else: gray = 192 new_img2[i, j][k] = np.uint8(gray) #影像量化等級為8的量化處理 for i in range(height): for j in range(width): for k in range(3): #對應BGR三分量 if img[i, j][k] < 32: gray = 0 elif img[i, j][k] < 64: gray = 32 elif img[i, j][k] < 96: gray = 64 elif img[i, j][k] < 128: gray = 96 elif img[i, j][k] < 160: gray = 128 elif img[i, j][k] < 192: gray = 160 elif img[i, j][k] < 224: gray = 192 else: gray = 224 new_img3[i, j][k] = np.uint8(gray) #用來正常顯示中文標簽 plt.rcParams['font.sans-serif']=['SimHei'] #顯示影像 titles = [u'(a) 原始影像', u'(b) 量化-L2', u'(c) 量化-L4', u'(d) 量化-L8'] images = [img, new_img1, new_img2, new_img3] for i in xrange(4): plt.subplot(2,2,i+1), plt.imshow(images[i], 'gray'), plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
輸出結果如圖6-4所示,該代碼呼叫matplotlib.pyplot庫繪制了四幅影像,其中(a)表示原始影像,(b)表示等級為2的量化處理,(c)表示等級為4的量化處理,(d)表示等級為8的量化處理,
1.3 K-Means聚類量化處理
上一小節的量化處理是通過遍歷影像中的所有像素點,進行灰度影像的幅度值離散化處理,本小節補充一個基于K-Means聚類演算法的量化處理程序,它能夠將彩色影像RGB像素點進行顏色分割和顏色量化,更多知識推薦大家學習前一篇文章,
# coding: utf-8 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始影像 img = cv2.imread('people.png') #影像二維像素轉換為一維 data = img.reshape((-1,3)) data = np.float32(data) #定義中心 (type,max_iter,epsilon) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) #設定標簽 flags = cv2.KMEANS_RANDOM_CENTERS #K-Means聚類 聚集成4類 compactness, labels, centers = cv2.kmeans(data, 4, None, criteria, 10, flags) #影像轉換回uint8二維型別 centers = np.uint8(centers) res = centers[labels.flatten()] dst = res.reshape((img.shape)) #影像轉換為RGB顯示 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) dst = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB) #用來正常顯示中文標簽 plt.rcParams['font.sans-serif']=['SimHei'] #顯示影像 titles = [u'原始影像', u'聚類量化 K=4'] images = [img, dst] for i in xrange(2): plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray'), plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
輸出結果如圖6-4所示,它通過K-Means聚類演算法將彩色人物影像的灰度聚集成四種顏色,
二.影像采樣處理
2.1 概述
影像采樣(Image Sampling)處理是將一幅連續影像在空間上分割成M×N個網格,每個網格用一個亮度值或灰度值來表示,其示意圖如圖6-5所示,
影像采樣的間隔越大,所得影像像素數越少,空間解析度越低,影像質量越差,甚至出現馬賽克效應;相反,影像采樣的間隔越小,所得影像像素數越多,空間解析度越高,影像質量越好,但資料量會相應的增大,圖6-6展示了不同采樣間隔的“Lena”圖,
2.2 操作
下面講述Python影像采樣處理相關代碼操作,其核心流程是建立一張臨時圖片,設定需要采樣的區域大小(如16×16),接著回圈遍歷原始影像中所有像素點,采樣區域內的像素點賦值相同(如左上角像素點的灰度值),最終實作影像采樣處理,代碼是進行16×16采樣的程序,
# -*- coding: utf-8 -*- import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始影像 img = cv2.imread('scenery.png') #獲取影像高度和寬度 height = img.shape[0] width = img.shape[1] #采樣轉換成16*16區域 numHeight = height/16 numwidth = width/16 #創建一幅影像 new_img = np.zeros((height, width, 3), np.uint8) #影像回圈采樣16*16區域 for i in range(16): #獲取Y坐標 y = i*numHeight for j in range(16): #獲取X坐標 x = j*numwidth #獲取填充顏色 左上角像素點 b = img[y, x][0] g = img[y, x][1] r = img[y, x][2] #回圈設定小區域采樣 for n in range(numHeight): for m in range(numwidth): new_img[y+n, x+m][0] = np.uint8(b) new_img[y+n, x+m][1] = np.uint8(g) new_img[y+n, x+m][2] = np.uint8(r) #顯示影像 cv2.imshow("src", img) cv2.imshow("", new_img) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
輸出結果如下圖所示:
同樣,可以對彩色影像進行采樣處理,下面的代碼將彩色風景影像采樣處理成8×8的馬賽克區域,
# -*- coding: utf-8 -*- import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始影像 img = cv2.imread('scenery.png') #獲取影像高度和寬度 height = img.shape[0] width = img.shape[1] #采樣轉換成8*8區域 numHeight = height/8 numwidth = width/8 #創建一幅影像 new_img = np.zeros((height, width, 3), np.uint8) #影像回圈采樣8*8區域 for i in range(8): #獲取Y坐標 y = i*numHeight for j in range(8): #獲取X坐標 x = j*numwidth #獲取填充顏色 左上角像素點 b = img[y, x][0] g = img[y, x][1] r = img[y, x][2] #回圈設定小區域采樣 for n in range(numHeight): for m in range(numwidth): new_img[y+n, x+m][0] = np.uint8(b) new_img[y+n, x+m][1] = np.uint8(g) new_img[y+n, x+m][2] = np.uint8(r) #顯示影像 cv2.imshow("src", img) cv2.imshow("Sampling", new_img) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
其輸出結果如圖所示,它將彩色風景影像采樣成8×8的區域,
但上述代碼存在一個問題,當影像的長度和寬度不能被采樣區域整除時,輸出影像的最右邊和最下邊的區域沒有被采樣處理,這里推薦讀者做個求余運算,將不能整除部門的區域也進行采樣處理,
2.3 區域馬賽克處理
前面講述的代碼是對整幅影像進行采樣處理,那么如何對影像的區域區域進行馬賽克處理呢?下面的代碼就實作了該功能,當滑鼠按下時,它能夠給滑鼠拖動的區域打上馬賽克,并按下“s”鍵保存影像至本地,
# -- coding:utf-8 -- import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始影像 im = cv2.imread('people.png', 1) #設定滑鼠左鍵開啟 en = False #滑鼠事件 def draw(event, x, y, flags, param): global en #滑鼠左鍵按下開啟en值 if event==cv2.EVENT_LBUTTONDOWN: en = True #滑鼠左鍵按下并且移動 elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_LBUTTONDOWN: #呼叫函式打馬賽克 if en: drawMask(y,x) #滑鼠左鍵彈起結束操作 elif event==cv2.EVENT_LBUTTONUP: en = False #影像區域采樣操作 def drawMask(x, y, size=10): #size*size采樣處理 m = x / size * size n = y / size * size print m, n #10*10區域設定為同一像素值 for i in range(size): for j in range(size): im[m+i][n+j] = im[m][n] #打開對話框 cv2.namedWindow('image') #呼叫draw函式設定滑鼠操作 cv2.setMouseCallback('image', draw) #回圈處理 while(1): cv2.imshow('image', im) #按ESC鍵退出 if cv2.waitKey(10)&0xFF==27: break #按s鍵保存圖片 elif cv2.waitKey(10)&0xFF==115: cv2.imwrite('sava.png', im) #退出視窗 cv2.destroyAllWindows()
其輸出結果如圖所示,它將人物的臉部進行馬賽克處理,
點擊關注,第一時間了解華為云新鮮技術~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/507148.html
標籤:其他
下一篇:jupyter使用虛擬環境
