欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用python PIL庫實(shí)現(xiàn)簡單驗(yàn)證碼的去噪方法步驟

 更新時(shí)間:2019年05月10日 14:28:35   作者:鍋爐房劉大爺  
這篇文章主要介紹了使用python PIL庫實(shí)現(xiàn)簡單驗(yàn)證碼的去噪方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

字符型圖片驗(yàn)證碼識(shí)別完整過程及Python實(shí)現(xiàn)的博主,我的大部分知識(shí)點(diǎn)都是從他那里學(xué)來的。

想要識(shí)別驗(yàn)證碼,收集足夠多的樣本后,首先要做的就是對(duì)驗(yàn)證碼原始圖片進(jìn)行處理,對(duì)驗(yàn)證碼識(shí)別分類之前,一般包括:將彩色圖片轉(zhuǎn)換成灰度圖、將灰度圖二值化和去除噪點(diǎn)三個(gè)基本過程。這里僅以比較簡單的驗(yàn)證碼為例,介紹一下如何通過python的PIL庫對(duì)圖片去噪。

首先看一下未經(jīng)處理的驗(yàn)證碼圖片:


對(duì)圖片處理主要使用了PIL庫的Image類。

1.彩色圖片轉(zhuǎn)換成灰度圖

首先使用Image的open方法打開上面的圖片,可以得到一個(gè)PIL.Image.Image對(duì)象,之后就可以調(diào)用convert、filter、point和putpixel等方法來處理圖片。

我們可以通過convert方法將上面的彩色圖片轉(zhuǎn)換成灰度圖:

# encoding=utf8
 
from PIL import Image
 
def main():
	image = Image.open('RandomPicture.png')
	imgry = image.convert('L')
	imgry.save('gray.png')
 
if __name__ == '__main__':
	main()

運(yùn)行結(jié)果:


通過保存的圖片可以看出來,已經(jīng)由原來的彩圖變成了灰度圖,或者也可以認(rèn)為是黑白圖。什么叫灰度圖?我們知道彩色圖片是由不同的顏色的像素組合到一起的,那灰度圖可以類似的認(rèn)為是由不同灰度值的像素組合在一起后呈現(xiàn)出來的。任何顏色都有紅、綠、藍(lán)三原色組成,假如原來某點(diǎn)的顏色為RGB(R,G,B),那么,我們可以通過下面幾種方法,將其轉(zhuǎn)換為灰度:

1.浮點(diǎn)算法:Gray=R*0.3+G*0.59+B*0.11
2.整數(shù)方法:Gray=(R*30+G*59+B*11)/100
3.移位方法:Gray =(R*76+G*151+B*28)>>8;
4.平均值法:Gray=(R+G+B)/3;
5.僅取綠色:Gray=G;

通過上述任一種方法求得Gray后,將原來的RGB(R,G,B)中的R,G,B統(tǒng)一用Gray替換,形成新的顏色RGB(Gray,Gray,Gray),用它替換原來的RGB(R,G,B)就是灰度圖了。

用代碼實(shí)現(xiàn)看一下:

# encoding=utf8
 
from PIL import Image
 
def main():
	image = Image.open('RandomPicture.png')
	print 'image mode: ', image.mode
	print image.getpixel((0, 0))
	print '-' * 40
	imgry = image.convert('L')
	print 'imgry mode: ', imgry.mode
	print imgry.getpixel((0, 0))
 
if __name__ == '__main__':
	main()

運(yùn)行結(jié)果:

image mode: RGB
(21, 10, 26)
----------------------------------------
imgry mode: L
15

代碼說明:

通過image.mode方法可以獲得當(dāng)前的PIL.Image.Image對(duì)象(也就是當(dāng)前打開的圖片)的mode值,而mode值表示圖片的單位顏色是由RGB三個(gè)值組成的還是由灰度值組成的;

而getpixel可以獲取某個(gè)像素的RGB值或者灰度值。我們知道圖片是由許多像素組成的,每個(gè)像素在圖片上都有一個(gè)對(duì)應(yīng)的坐標(biāo)x和y,而“(0, 0)”就表示該圖片左上角頂點(diǎn)的像素。

由上面的結(jié)果我們可以知道,在將圖片轉(zhuǎn)換成灰度圖之前,“(0, 0)”代表的像素的顏色是由RGB組成的:(21, 10, 26);在通過concert將彩色圖片轉(zhuǎn)換成灰度后,“(0, 0)”代表的像素的顏色值就變成了一個(gè)值:“15”,通過打印imgry.mode我們也可以知道,此時(shí)圖片已經(jīng)變成了灰度圖,它的每一個(gè)像素的顏色都變成了一個(gè)灰度值。

其實(shí)這時(shí)候我們也可以簡單的計(jì)算一下,使用前面說的浮點(diǎn)算法將上面的(21, 10, 26)三個(gè)值帶入計(jì)算:

>>> 21*0.3+10*0.59+26*0.11
15.059999999999999

結(jié)果顯示確實(shí)由浮點(diǎn)算法將RGB值變成了灰度值。

2.灰度圖二值化

我們已經(jīng)得到了灰度圖,接下來就是將灰度圖二值化。所謂二值化就是將灰度圖像轉(zhuǎn)換成由黑白二色組成的圖像。思路就是確定一個(gè)閾值,大于閾值的像素表示為白色,小于閾值的像素表示為黑色,以此將圖片的像素(灰度值)劃分為兩部分:0和1,例如0代表黑色,1代表白色,然后我們就可以用一串0和1組成的數(shù)字來表示一張圖片。

將灰度圖二值化會(huì)用到point方法,它可以接收一個(gè)灰度轉(zhuǎn)二值的映射table,具體原理暫時(shí)還沒弄明白,代碼實(shí)現(xiàn)過程是這樣的:

# encoding=utf8
 
from PIL import Image
 
def get_bin_table(threshold=115):
	'''
	獲取灰度轉(zhuǎn)二值的映射table
	0表示黑色,1表示白色
	'''
	table = []
	for i in range(256):
		if i < threshold:
			table.append(0)
		else:
			table.append(1)
	return table
 
def main():
	image = Image.open('RandomPicture.png')
	imgry = image.convert('L')
	table = get_bin_table()
	binary = imgry.point(table, '1')
	binary.save('binary.png')
 
if __name__ == '__main__':
	main()

運(yùn)行結(jié)果:


通過結(jié)果不難看出,我們已經(jīng)將最開始的彩色圖由灰度圖轉(zhuǎn)變成了僅由黑白二色組成的圖片,實(shí)現(xiàn)了二值化。這里需要說明的是,threshold參數(shù)值針對(duì)當(dāng)前的驗(yàn)證碼圖片合適,該值需要根據(jù)驗(yàn)證碼類型不同進(jìn)行調(diào)試來確定。

然后我們?cè)倏纯?0, 0)坐標(biāo)代表的像素的顏色值是什么:

# encoding=utf8
 
from PIL import Image
 
def get_bin_table(threshold=115):
	'''
	獲取灰度轉(zhuǎn)二值的映射table
	0表示黑色,1表示白色
	'''
	table = []
	for i in range(256):
		if i < threshold:
			table.append(0)
		else:
			table.append(1)
	return table
 
def main():
	image = Image.open('RandomPicture.png')
	print 'image mode: ', image.mode
	print image.getpixel((0, 0))
	co = image.getcolors()
	print co
	print '-' * 40
	imgry = image.convert('L')
	print 'imgry mode: ', imgry.mode
	print imgry.getpixel((0, 0))
	co = imgry.getcolors()
	print co
	print '-' * 40
	table = get_bin_table()
	binary = imgry.point(table, '1')
	print 'binary mode: ', binary.mode
	print binary.getpixel((0, 0))
	co = binary.getcolors()
	print co
 
if __name__ == '__main__':
	main()

運(yùn)行結(jié)果:

image mode: RGB
(21, 10, 26)
None
----------------------------------------
imgry mode: L
15
[(1, 2), (2, 3), (1, 4), (1, 5), (4, 6), (3, 8), (3, 9), (6, 10), (4, 11), (4, 12), (7, 13), (8, 14), (3, 15), (12, 16), (7, 17), (6, 18), (5, 19), (13, 20), (9, 21), (9, 22), (4, 23), (5, 24), (7, 25), (3, 26), (6, 27), (7, 28), (3, 29), (3, 30), (3, 31), (5, 32), (1, 33), (3, 35), (2, 36), (2, 37), (2, 38), (2, 39), (1, 41), (3, 42), (1, 43), (2, 44), (7, 45), (3, 46), (5, 47), (1, 48), (3, 49), (3, 50), (3, 51), (5, 52), (4, 53), (1, 54), (7, 55), (7, 56), (10, 57), (4, 58), (5, 59), (6, 60), (5, 61), (12, 62), (7, 63), (10, 64), (12, 65), (14, 66), (15, 67), (11, 68), (9, 69), (11, 70), (7, 71), (9, 72), (5, 73), (10, 74), (5, 75), (5, 76), (5, 77), (8, 78), (7, 79), (3, 80), (5, 81), (6, 82), (5, 83), (3, 84), (3, 85), (6, 86), (2, 87), (3, 88), (2, 90), (3, 91), (1, 93), (2, 94), (3, 95), (1, 96), (3, 97), (2, 99), (3, 100), (3, 101), (1, 102), (3, 104), (4, 105), (1, 106), (3, 108), (4, 110), (4, 111), (4, 112), (3, 113), (3, 114), (5, 115), (2, 116), (3, 117), (8, 118), (8, 119), (8, 120), (7, 121), (9, 122), (9, 123), (11, 124), (11, 125), (2, 126), (10, 127), (9, 128), (7, 129), (13, 130), (11, 131), (11, 132), (9, 133), (16, 134), (11, 135), (12, 136), (8, 137), (14, 138), (12, 139), (13, 140), (20, 141), (22, 142), (19, 143), (14, 144), (23, 145), (17, 146), (10, 147), (18, 148), (13, 149), (11, 150), (26, 151), (16, 152), (14, 153), (11, 154), (17, 155), (10, 156), (12, 157), (12, 158), (20, 159), (18, 160), (16, 161), (22, 162), (20, 163), (16, 164), (13, 165), (14, 166), (13, 167), (11, 168), (17, 169), (8, 170), (16, 171), (20, 172), (12, 173), (10, 174), (10, 175), (10, 176), (11, 177), (7, 178), (8, 179), (7, 180), (5, 181), (7, 182), (4, 183), (7, 184), (4, 185), (4, 186), (5, 187), (6, 188), (2, 189), (1, 190), (4, 191), (6, 192), (12, 193), (8, 194), (10, 195), (3, 196), (13, 197), (9, 198), (19, 199), (18, 200), (20, 201), (16, 202), (18, 203), (24, 204), (33, 205), (25, 206), (33, 207), (38, 208), (31, 209), (46, 210), (39, 211), (53, 212), (54, 213), (33, 214), (42, 215), (54, 216), (60, 217), (50, 218), (36, 219), (48, 220), (32, 221), (45, 222), (28, 223), (24, 224), (21, 225), (19, 226), (21, 227), (13, 228), (12, 229), (12, 230), (13, 231), (5, 232), (8, 233), (4, 234), (5, 235), (1, 236), (1, 237), (2, 238), (1, 239), (1, 240), (1, 242), (1, 243)]
----------------------------------------
binary mode: 1
0
[(503, 0), (1993, 1)]

代碼說明:

通過binary mode的值我們可以知道二值化后得到的圖片的像素值由0或1表示,而且當(dāng)前(0, 0)代表的像素值的為0,它代表黑色,通過上面的圖片我們也可以知道,左上角頂點(diǎn)確實(shí)是黑色的。

上面的代碼中我們還使用了getcolors方法,它用來返回像素信息,是一個(gè)含有元素的列表:[(該種像素的數(shù)量,(該種像素)),(...),...],當(dāng)該列表特別大的時(shí)候,它會(huì)返回None,這也是為什么上面彩色圖片調(diào)用getcolors的時(shí)候會(huì)返回None。而[(503, 0), (1993, 1)]就表示我們得到的二值化黑白圖片,由503個(gè)黑色像素點(diǎn)和1993個(gè)白色像素點(diǎn)組成。

通過binary.size我們可以得到二值化后的黑白圖片的width和height值:(78, 32),它就表示該圖片由78X32個(gè)像素點(diǎn)組成,正好等于503+1993的和。(78, 32)也說明該圖片橫向上共有32行,每行有78個(gè)像素點(diǎn)。將由0和1表示的圖片打印出來看一下:

# encoding=utf8
 
from PIL import Image
 
def get_bin_table(threshold=115):
	'''
	獲取灰度轉(zhuǎn)二值的映射table
	0表示黑色,1表示白色
	'''
	table = []
	for i in range(256):
		if i < threshold:
			table.append(0)
		else:
			table.append(1)
	return table
 
def main():
	image = Image.open('RandomPicture.png')
	imgry = image.convert('L')
	table = get_bin_table()
	binary = imgry.point(table, '1')
	width, height = binary.size
	lis = binary.getdata()	# 返回圖片所有的像素值,要使用list()才能顯示出具體數(shù)值
	lis = list(lis)
	start = 0
	step = width
	for i in range(height):
		for p in lis[start: start+step]:
			if p == 1:	# 將白色的點(diǎn)變成空格,方便人眼看
				p = ' '
			print p,
		print
		start += step
 
if __name__ == '__main__':
	main()

運(yùn)行結(jié)果:


通過上面的結(jié)果已經(jīng)大致可以看出該圖片表示的就是“959c”。

3.去除噪點(diǎn)

由上面的結(jié)果也不難看出,除了表示“959c”的“0”,圖片中還有其他的“0”代表的“噪點(diǎn)”,我們要盡可能的去除它們,方便后期的識(shí)別訓(xùn)練。

對(duì)于去除噪點(diǎn),我這里也是借鑒了字符型圖片驗(yàn)證碼識(shí)別完整過程及Python實(shí)現(xiàn)里面的“九宮格”方法,代碼實(shí)現(xiàn):

# encoding=utf8
 
from PIL import Image
 
def sum_9_region_new(img, x, y):
	'''確定噪點(diǎn) '''
	cur_pixel = img.getpixel((x, y)) # 當(dāng)前像素點(diǎn)的值
	width = img.width
	height = img.height
 
	if cur_pixel == 1: # 如果當(dāng)前點(diǎn)為白色區(qū)域,則不統(tǒng)計(jì)鄰域值
		return 0
 
	# 因當(dāng)前圖片的四周都有黑點(diǎn),所以周圍的黑點(diǎn)可以去除
	if y < 3: # 本例中,前兩行的黑點(diǎn)都可以去除
		return 1
	elif y > height - 3: # 最下面兩行
		return 1
	else: # y不在邊界
		if x < 3: # 前兩列
			return 1
		elif x == width - 1: # 右邊非頂點(diǎn)
			return 1
		else: # 具備9領(lǐng)域條件的
			sum = img.getpixel((x - 1, y - 1)) \
				 + img.getpixel((x - 1, y)) \
				 + img.getpixel((x - 1, y + 1)) \
				 + img.getpixel((x, y - 1)) \
				 + cur_pixel \
				 + img.getpixel((x, y + 1)) \
				 + img.getpixel((x + 1, y - 1)) \
				 + img.getpixel((x + 1, y)) \
				 + img.getpixel((x + 1, y + 1))
			return 9 - sum
 
def collect_noise_point(img):
	'''收集所有的噪點(diǎn)'''
	noise_point_list = []
	for x in range(img.width):
		for y in range(img.height):
			res_9 = sum_9_region_new(img, x, y)
			if (0 < res_9 < 3) and img.getpixel((x, y)) == 0: # 找到孤立點(diǎn)
				pos = (x, y)
				noise_point_list.append(pos)
	return noise_point_list
 
def remove_noise_pixel(img, noise_point_list):
	'''根據(jù)噪點(diǎn)的位置信息,消除二值圖片的黑點(diǎn)噪聲'''
	for item in noise_point_list:
		img.putpixel((item[0], item[1]), 1)
 
def get_bin_table(threshold=115):
	'''獲取灰度轉(zhuǎn)二值的映射table,0表示黑色,1表示白色'''
	table = []
	for i in range(256):
		if i < threshold:
			table.append(0)
		else:
			table.append(1)
	return table
 
def main():
	image = Image.open('RandomPicture.png')
	imgry = image.convert('L')
	table = get_bin_table()
	binary = imgry.point(table, '1')
	noise_point_list = collect_noise_point(binary)
	remove_noise_pixel(binary, noise_point_list)
	binary.save('finaly.png')
 
if __name__ == '__main__':
	main()

運(yùn)行結(jié)果:


通過截圖可以知道,我們已經(jīng)去除了圖片四周的噪點(diǎn)以及一些孤立的噪點(diǎn)。

還要再說一句的就是,除了上面的步驟,我們還可以通過PIL的ImageEnhance,和ImageFilter對(duì)圖片做其他處理(例如增加對(duì)比度、亮度、銳化等),這里就不舉例說明了,因?yàn)椴煌膱D片經(jīng)過這些處理后,可能效果會(huì)不同。

最后,要感謝這些博主的分享,為我學(xué)習(xí)驗(yàn)證碼識(shí)別相關(guān)知識(shí)提供了不少參考:

字符型圖片驗(yàn)證碼識(shí)別完整過程及Python實(shí)現(xiàn)

Python3.5+sklearn 使用SVM自動(dòng)識(shí)別字母驗(yàn)證碼

python簡單驗(yàn)證碼識(shí)別

基于Python的PIL庫學(xué)習(xí)(一)

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • numpy模塊中axis的理解與使用

    numpy模塊中axis的理解與使用

    而在numpy中有很多的函數(shù)都涉及到axis,numpy中的軸axis是很重要的,許多numpy的操作根據(jù)axis的取值不同,作出的操作也不相同,這篇文章主要給大家介紹了關(guān)于numpy模塊中axis的理解與使用的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • Python?operator模塊的使用詳解

    Python?operator模塊的使用詳解

    本文主要介紹了Python?operator模塊的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧<BR>
    2023-06-06
  • PyQt5 多窗口連接實(shí)例

    PyQt5 多窗口連接實(shí)例

    今天小編就為大家分享一篇PyQt5 多窗口連接實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-06-06
  • python使用鄰接矩陣構(gòu)造圖代碼示例

    python使用鄰接矩陣構(gòu)造圖代碼示例

    這篇文章主要介紹了python使用鄰接矩陣構(gòu)造圖代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • 使用Python實(shí)現(xiàn)圖像有效壓縮的方法

    使用Python實(shí)現(xiàn)圖像有效壓縮的方法

    在數(shù)字時(shí)代,圖像作為信息傳遞的重要媒介,在網(wǎng)頁設(shè)計(jì)、移動(dòng)應(yīng)用和多媒體制作中扮演著不可或缺的角色,本文將詳細(xì)介紹如何使用Python,一個(gè)功能強(qiáng)大且易于學(xué)習(xí)的編程語言,來實(shí)現(xiàn)圖像的有效壓縮,感興趣的朋友可以參考下
    2024-03-03
  • Python從MySQL數(shù)據(jù)庫中面抽取試題,生成試卷

    Python從MySQL數(shù)據(jù)庫中面抽取試題,生成試卷

    這篇文章主要介紹了Python如何從MySQL數(shù)據(jù)庫中面抽取試題,生成試卷,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2021-01-01
  • python使用Plotly繪圖工具繪制散點(diǎn)圖、線形圖

    python使用Plotly繪圖工具繪制散點(diǎn)圖、線形圖

    這篇文章主要為大家詳細(xì)介紹了python使用Plotly繪圖工具繪制散點(diǎn)圖、線形圖,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • 使用seaborn繪制強(qiáng)化學(xué)習(xí)中的圖片問題

    使用seaborn繪制強(qiáng)化學(xué)習(xí)中的圖片問題

    這篇文章主要介紹了使用seaborn繪制強(qiáng)化學(xué)習(xí)中的圖片問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 詳解python中的變量

    詳解python中的變量

    這篇文章主要為大家詳細(xì)介紹了python的變量,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • python基于celery實(shí)現(xiàn)異步任務(wù)周期任務(wù)定時(shí)任務(wù)

    python基于celery實(shí)現(xiàn)異步任務(wù)周期任務(wù)定時(shí)任務(wù)

    這篇文章主要介紹了python基于celery實(shí)現(xiàn)異步任務(wù)周期任務(wù)定時(shí)任務(wù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12

最新評(píng)論