最近一段時間學習並作的都是對圖像進行處理,其實本身也是新手,各類嘗試,因此我這個門外漢想總結一下本身學習的東西,圖像處理的流程。可是動起筆來想總結,一下殊不知道本身要寫什麼,那就把本身作過的類似圖片搜索的流程整理一下,想到什麼說什麼吧。html
首先在進行圖片灰度化處理以前,我以爲有必要了解一下爲何要進行灰度化處理。python
將彩色圖像轉化爲灰度圖像的過程是圖像的灰度化處理。彩色圖像中的每一個像素的顏色由R,G,B三個份量決定,而每一個份量中可取值0-255,這樣一個像素點能夠有1600多萬(256*256*256=1677256)的顏色的變化範圍。而灰度圖像是R,G,B三個份量相同的一種特殊的彩色圖像,其中一個像素點的變化範圍爲256種,因此在數字圖像處理中通常將各類格式的圖像轉化爲灰度圖像以使後續的圖像的計算量少一些。灰度圖像的描述與彩色圖像同樣仍然反映了整副圖像的總體和局部的色度和高亮等級的分佈和特徵。算法
灰度化處理就是將一幅色彩圖像轉化爲灰度圖像的過程。彩色圖像分爲R,G,B三個份量,分別顯示出紅綠藍等各類顏色,灰度化就是使彩色的R,G,B份量相等的過程。灰度值大的像素點比較亮(像素值最大爲255,爲白色),反之比較暗(像素最下爲0,爲黑色)。windows
1)最大值法:使轉化後的R,G,B得值等於轉化前3個值中最大的一個,即:R=G=B=max(R,G,B)。這種方法轉換的灰度圖亮度很高。數組
2)平均值法:是轉化後R,G,B的值爲轉化前R,G,B的平均值。即:R=G=B=(R+G+B)/3。這種方法產生的灰度圖像比較柔和。 網絡
3)加權平均值法:按照必定權值,對R,G,B的值加權平均,即:分別爲R,G,B的權值,取不一樣的值造成不一樣的灰度圖像。因爲人眼對綠色最爲敏感,紅色次之,對藍色的敏感性最低,所以使將獲得較易識別的灰度圖像。通常時,獲得的灰度圖像效果最好。app
下面的這種方法,在讀取圖片的時候,直接將圖片轉化爲灰度化:less
import cv2 img = cv2.imread(photo_file, cv2.IMREAD_GRAYSCALE)
獲得的img是一個函數。ide
下面的方法,先讀取圖片,而後再轉化爲灰度圖。函數
import cv2 img = cv2.imread(photo_file) # Y = 0.299R + 0.587G + 0.114B grey_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
首先讀取圖片,而後灰度化,最後轉化爲數組
import numpy as np form PIL import Image # 使用PIL庫中的Image模塊 # L = 0.299R + 0.587G + 0.114B img2 = Image.open(photo_file) grey_img2 = img2.convert('L') grey_img22 = np.array(grey_img2) print(type(grey_img22))
使用python中的圖像處理庫PIL來實現不一樣圖像格式的轉化,對於彩色圖像,無論其圖像格式是PNG,仍是BMP,仍是JPG,在PIL中,使用Image模塊的open()函數打開後,返回的圖像對象的模式都是「RGB」。而對於灰度圖像,無論其圖像格式是PNG,仍是BMP,或者JPG,打開後,其模式爲「L」。
from PIL import Image # load a color image im = Image.open('durant.jpg' ) # convert to grey level image Lim = im.convert('L' ) Lim.save('grey.jpg' ) # setup a converting table with constant threshold threshold = 185 table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) # convert to binary image by the table bim = Lim.point(table, '1' ) bim.save('durant_grey.jpg' )
Convert()會根據傳入參數的不一樣將圖像變成不一樣的模式。PIL中有九種不一樣模式。分別爲1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。
模式‘1’爲二值圖像,非黑即白。可是它每一個像素用8個bit表示, 0表示黑,255表示白。 模式‘L’爲灰色圖像它的每一個像素用8個bit表示,0表示黑, 255表示白,其餘數字表示不一樣的灰度。在PIL中,從模式「RGB」轉 換爲「L」模式是按照下面的公式轉換的: L = R * 299/1000 + G * 587/1000+ B * 114/1000 模式「P」爲8位彩色圖像,它的每一個像素用8個bit表示,其對應的 彩色值是按照調色板查詢出來的。 模式「RGBA」爲32位彩色圖像,它的每一個像素用32個bit表示,其 中24bit表示紅色、綠色和藍色三個通道,另外8bit表示alpha通道, 即透明通道。 模式「CMYK」爲32位彩色圖像,它的每一個像素用32個bit表示。模 式「CMYK」就是印刷四分色模式,它是彩色印刷時採用的一種套色模 式,利用色料的三原色混色原理,加上黑色油墨,共計四種顏色混合 疊加,造成所謂「全綵印刷」。 模式「YCbCr」爲24位彩色圖像,它的每一個像素用24個bit表示。 YCbCr其中Y是指亮度份量,Cb指藍色色度份量,而Cr指紅色色度分 量。人的肉眼對視頻的Y份量更敏感,所以在經過對色度份量進行子 採樣來減小色度份量後,肉眼將察覺不到的圖像質量的變化。 模式「RGB」轉換爲「YCbCr」的公式以下: Y= 0.257R+0.504G+0.098B+16 Cb = -0.148R-0.291G+0.439B+128 Cr = 0.439R-0.368G-0.071*B+128 模式「I」爲32位整型灰色圖像,它的每一個像素用32個bit表示,0表示黑, 255表示白,(0,255)之間的數字表示不一樣的灰度。在PIL中,從模式「RGB」 轉換爲「I」模式是按照下面的公式轉換的: I = R * 299/1000 + G * 587/1000 + B * 114/1000 模式「F」爲32位浮點灰色圖像,它的每一個像素用32個bit表示,0表示黑, 255表示白,(0,255)之間的數字表示不一樣的灰度。在PIL中,從模式「RGB」轉 換爲「F」模式是按照下面的公式轉換的: F = R * 299/1000+ G * 587/1000 + B * 114/1000
圖像加強是圖像模式識別中很是重要的圖像預處理過程。圖像加強的目的是經過對圖像中的信息進行處理,使得有利於模式識別的信息獲得加強,不利於模式識別的信息被抑制,擴大圖像中不一樣物體特徵之間的差異,爲圖像的信息提取及其識別奠基良好的基礎。圖像加強按實現方法不一樣可分爲點加強、空域加強和頻域加強。
點加強
點加強主要指圖像灰度變換和幾何變換。圖像的灰度變換也稱爲點運算、對比度加強或對比度拉伸,它是圖像數字化軟件和圖像顯示軟件的重要組成部分。
灰度變換是一種既簡單又重要的技術,它能讓用戶改變圖像數據佔據的灰度範圍。一幅輸入圖像通過灰度變換後將產生一幅新的輸出圖像,由輸入像素點的灰度值決定相應的輸出像素點的灰度值。灰度變換不會改變圖像內的空間關係。
圖像的幾何變換是圖像處理中的另外一種基本變換。它一般包括圖像的平移、圖像的鏡像變換、圖像的縮放和圖像的旋轉。經過圖像的幾何變換能夠實現圖像的最基本的座標變換及縮放功能。
空域加強
圖像的空間信息能夠反映圖像中物體的位置 、形狀、大小等特徵,而這些特徵能夠經過必定的物理模式來描述。例如,物體的邊緣輪廓因爲灰度值變化劇烈通常出現高頻率特徵,而一個比較平滑的物體內部因爲灰度值比較均一則呈現低頻率特徵。所以,根據須要能夠分別加強圖像的高頻和低頻特徵。對圖像的高頻加強能夠突出物體的邊緣輪廓,從而起到銳化圖像的做用。例如,對於人臉的比對查詢,就須要經過高頻加強技術來突出五宮的輪廓。相應地,對圖像的低頻部分進行加強能夠對圖像進行平滑處理,通常用於圖像的噪聲消除。
頻域加強
圖像的空域加強通常只是對數字圖像進行局部加強,而圖像的頻域加強能夠對圖像進行全局加強。頻域加強技術是在數字圖像的頻率域空間對圖像進行濾波,所以須要將圖像從空間域變換到頻率域,通常經過傅里葉變換實現。在頻率域空間的濾波與空域濾波同樣能夠經過卷積實現,所以傅里葉變換和和卷積理論是頻域濾波技術的基礎。
圖像加強的主要目的有:改變圖像的灰度等級,提升圖像對比度,消除邊緣和噪聲,平滑圖像;突出邊緣或者線性地物,銳化圖像;合成彩色圖像;壓縮圖像數據量,突出主要信息等。
圖像加強的主要內容有:空間域加強、頻率域加強、彩色加強、多圖像代數運算、多光譜圖像加強等。
在圖像分類任務中,圖像數據加強通常是大多數人會採用的方法之一,這是因爲深度學習對數據集的大小有必定的要求,若原始的數據集比較小,沒法很好地知足網絡模型的訓練,從而影響模型的性能,而圖像加強是對原始圖像進行必定的處理以擴充數據集,可以在必定程度上提高模型的性能。
from PIL import Image from PIL import ImageEnhance # 原始圖像 image = Image.open('deal_with/A1.jpg') image.show() #亮度加強 enh_bri = ImageEnhance.Brightness(image) brightness = 1.5 image_brightened = enh_bri.enhance(brightness) image_brightened.show() image_brightened.save("image_brightened.jpg") #色度加強 enh_col = ImageEnhance.Color(image) color = 1.5 image_colored = enh_col.enhance(color) image_colored.show() image_colored.save("image_colored.jpg") #對比度加強 enh_con = ImageEnhance.Contrast(image) contrast = 1.5 image_contrasted = enh_con.enhance(contrast) image_contrasted.show() image_contrasted.save("image_contrasted.jpg") #銳度加強 enh_sha = ImageEnhance.Sharpness(image) sharpness = 3.0 image_sharped = enh_sha.enhance(sharpness) image_sharped.show() image_sharped.save("image_sharped.jpg")
原圖:
亮度加強:
色度加強:
對比度加強:
銳度加強:
對圖像進行翻轉是最流行的圖像數據加強方法之一,這主要是因爲翻轉圖像操做的代碼簡單,以及對於大多數問題而言,對圖像進行翻轉操做可以提高模型的性能。下面的模型能夠看到人是朝右而不是朝左邊。
將須要處理的圖片所放到指定尺寸,縮放後圖片大小由圖片的信息量和複雜度決定。譬如,一些簡單的圖標之類圖像包含的信息量少,複雜度低,能夠縮放小一點。風景等複雜場景信息量大,複雜度高就不能縮放過小,容易丟失重要信息。根據本身需求,彈性的縮放。在效率和準確度之間維持平衡。
一般對比圖像類似度和顏色關係不是很大,因此處理爲灰度圖,減小後期計算的複雜度。若是有特殊需求則保留圖像色彩。
此處開始,與傳統的哈希算法不一樣:分別依次計算圖像每行像素點的平均值,記錄每行像素點的平均值。每個平均值對應着一行的特徵。
對獲得的全部平均值進行計算方差,獲得的方差就是圖像的特徵值。方差能夠很好的反應每行像素特徵的波動,既記錄了圖片的主要信息。
通過上面的計算以後,每張圖都會生成一個特徵值(方差)。到此,比較圖像類似度就是比較圖像生成方差的接近成程度。
一組數據方差的大小能夠判斷穩定性,多組數據方差的接近程度能夠反應數據波動的接近程度。咱們不關注方差的大小,只關注兩個方差的差值的大小。方差差值越小圖像越類似!
import cv2 import matplotlib.pyplot as plt #計算方差 def getss(list): #計算平均值 avg=sum(list)/len(list) #定義方差變量ss,初值爲0 ss=0 #計算方差 for l in list: ss+=(l-avg)*(l-avg)/len(list) #返回方差 return ss #獲取每行像素平均值 def getdiff(img): #定義邊長 Sidelength=30 #縮放圖像 img=cv2.resize(img,(Sidelength,Sidelength),interpolation=cv2.INTER_CUBIC) #灰度處理 gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #avglist列表保存每行像素平均值 avglist=[] #計算每行均值,保存到avglist列表 for i in range(Sidelength): avg=sum(gray[i])/len(gray[i]) avglist.append(avg) #返回avglist平均值 return avglist #讀取測試圖片 img1=cv2.imread("james.jpg") diff1=getdiff(img1) print('img1:',getss(diff1)) #讀取測試圖片 img11=cv2.imread("durant.jpg") diff11=getdiff(img11) print('img11:',getss(diff11)) ss1=getss(diff1) ss2=getss(diff11) print("兩張照片的方差爲:%s"%(abs(ss1-ss2))) x=range(30) plt.figure("avg") plt.plot(x,diff1,marker="*",label="$jiames$") plt.plot(x,diff11,marker="*",label="$durant$") plt.title("avg") plt.legend() plt.show() cv2.waitKey(0) cv2.destroyAllWindows()
img1: 357.03162469135805 img11: 202.56193703703704 兩張照片的方差爲:154.469687654321
實驗環境開始設置了圖片像素值,並且進行灰度化處理,此方法比對圖像類似對不一樣的圖片方差很大,結果很明顯,可是對比比較類似,特別類似的圖片不適應。
"感知哈希算法"(Perceptual hash algorithm),它的做用是對每張圖片生成一個"指紋"(fingerprint)字符串,而後比較不一樣圖片的指紋。結果越接近,就說明圖片越類似。
將圖片縮小到8x8的尺寸,總共64個像素。這一步的做用是去除圖片的細節,只保留結構、明暗等基本信息,摒棄不一樣尺寸、比例帶來的圖片差別。
將縮小後的圖片,轉爲64級灰度。也就是說,全部像素點總共只有64種顏色。
計算全部64個像素的灰度平均值
將每一個像素的灰度,與平均值進行比較。大於或等於平均值,記爲1;小於平均值,記爲0。
將上一步的比較結果,組合在一塊兒,就構成了一個64位的整數,這就是這張圖片的指紋。組合的次序並不重要,只要保證全部圖片都採用一樣次序就好了。
獲得指紋之後,就能夠對比不一樣的圖片,看看64位中有多少位是不同的。在理論上,這等同於計算"漢明距離"(Hamming distance)。若是不相同的數據位不超過5,就說明兩張圖片很類似;若是大於10,就說明這是兩張不一樣的圖片。
此算法參考博客:http://www.ruanyifeng.com/blog/2011/07 /principle_of_similar_image_search.html 可是未實現代碼,代碼以下:
#!/usr/bin/python import glob import os import sys from PIL import Image EXTS = 'jpg', 'jpeg', 'JPG', 'JPEG', 'gif', 'GIF', 'png', 'PNG' def avhash(im): if not isinstance(im, Image.Image): im = Image.open(im) im = im.resize((8, 8), Image.ANTIALIAS).convert('L') avg = reduce(lambda x, y: x + y, im.getdata()) / 64. return reduce(lambda x, (y, z): x | (z << y), enumerate(map(lambda i: 0 if i < avg else 1, im.getdata())), 0) def hamming(h1, h2): h, d = 0, h1 ^ h2 while d: h += 1 d &= d - 1 return h if __name__ == '__main__': if len(sys.argv) <= 1 or len(sys.argv) > 3: print "Usage: %s image.jpg [dir]" % sys.argv[0] else: im, wd = sys.argv[1], '.' if len(sys.argv) < 3 else sys.argv[2] h = avhash(im) os.chdir(wd) images = [] for ext in EXTS: images.extend(glob.glob('*.%s' % ext)) seq = [] prog = int(len(images) > 50 and sys.stdout.isatty()) for f in images: seq.append((f, hamming(avhash(f), h))) if prog: perc = 100. * prog / len(images) x = int(2 * perc / 5) print '\rCalculating... [' + '#' * x + ' ' * (40 - x) + ']', print '%.2f%%' % perc, '(%d/%d)' % (prog, len(images)), sys.stdout.flush() prog += 1 if prog: print for f, ham in sorted(seq, key=lambda i: i[1]): print "%d\t%s" % (ham, f)
C++: int waitKey(int delay=0) Python: cv2.waitKey([delay]) → retval C: int cvWaitKey(int delay=0 ) Python: cv.WaitKey(delay=0) → int
waitKey() 函數的功能是不斷地刷新圖像,頻率時間爲delay,單位爲ms。返回值爲當前鍵盤按鍵值。
1,waitKey() 這個函數是在一個給定的時間內(單位ms)等待用戶按鍵觸發;若是用戶沒有按下鍵,則繼續等待(循環)。
2,若是設置waitKey(0),則表示程序會無限制的等待用戶的按鍵事件。
3,用OpenCV來顯示圖像或者視頻時,若是後面不加cvWaitKey這個函數,基本上是顯示不出來的。
4,顯示圖像,通常要在cvShowImage()函數後面加一句cvWaitKey(0);不然圖像沒法正常顯示。
def waitKey(delay=None): # real signature unknown; restored from __doc__ """ waitKey([, delay]) -> retval . @brief Waits for a pressed key. . . The function waitKey waits for a key event infinitely (when \f$\texttt{delay}\leq 0\f$ ) or for delay . milliseconds, when it is positive. Since the OS has a minimum time between switching threads, the . function will not wait exactly delay ms, it will wait at least delay ms, depending on what else is . running on your computer at that time. It returns the code of the pressed key or -1 if no key was . pressed before the specified time had elapsed. . . @note . . This function is the only method in HighGUI that can fetch and handle events, so it needs to be . called periodically for normal event processing unless HighGUI is used within an environment that . takes care of event processing. . . @note . . The function only works if there is at least one HighGUI window created and the window is active. . If there are several HighGUI windows, any of them can be active. . . @param delay Delay in milliseconds. 0 is the special value that means "forever". """ pass
1,斜坡面上,一階微分一直不爲0 ;二階微分只有終點和起點不爲0 2,一階微分產生較粗的邊緣,二階微分則細得多 3,一階微分處理通常對灰度階梯有較強的響應;二階微分處理細節有較強的響應
OpenCV的全稱open Sourse Computer Vision Library ,是一個跨平臺的計算機視覺庫,OpenCV可用於開發實時的圖像處理,計算機視覺以及模式識別的程序。
OpenCV是用C++語言編寫,它的主要接口也是C++語言,可是依然保留了大量的C語言接口,該庫也有大量的Python,Java和MATLAB的接口,另外,一個使用CUDA的GPU接口也用於2010.9 開始實現。
雖然python很強大,並且也有本身的圖像處理庫PIL,可是相對於OpenCV來說,它仍是弱小不少。跟不少開源軟件同樣OpenCV也提供了完善的python接口,很是便於調用。OpenCV 的穩定版是2.4.8,最新版是3.0,包含了超過2500個算法和函數,幾乎任何一個能想到的成熟算法均可以經過調用OpenCV的函數來實現,超級方便。
錯誤以下:
1,進入cmd控制檯,查看python版本
2 根據本身用的python版本,下載對應的OpenCV
https://www.lfd.uci.edu/~gohlke/pythonlibs/
3,下載numpy,對應的版本
https://pypi.python.org/pypi/numpy
cp36表明着匹配python3.6版本。 win3二、amd64表明着32位、64位系統。
4,安裝OpenCV,下載下來是一個whl格式文件,把此文件放在安裝的文件名下,直接安裝。
就這樣安裝成功。
參考文獻:https://blog.csdn.net/wsp_1138886114/article/details/81368890