欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

python身份驗(yàn)證函數(shù) 身份證校驗(yàn)Python

如何利用Python做簡(jiǎn)單的驗(yàn)證碼識(shí)別

1???摘要

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、虛擬空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、梁子湖網(wǎng)站維護(hù)、網(wǎng)站推廣。

驗(yàn)證碼是目前互聯(lián)網(wǎng)上非常常見(jiàn)也是非常重要的一個(gè)事物,充當(dāng)著很多系統(tǒng)的?防火墻?功能,但是隨時(shí)OCR技術(shù)的發(fā)展,驗(yàn)證碼暴露出來(lái)的安全問(wèn)題也越來(lái)越嚴(yán)峻。本文介紹了一套字符驗(yàn)證碼識(shí)別的完整流程,對(duì)于驗(yàn)證碼安全和OCR識(shí)別技術(shù)都有一定的借鑒意義。

然后經(jīng)過(guò)了一年的時(shí)間,筆者又研究和get到了一種更強(qiáng)大的基于CNN卷積神經(jīng)網(wǎng)絡(luò)的直接端到端的驗(yàn)證識(shí)別技術(shù)(文章不是我的,然后我把源碼整理了下,介紹和源碼在這里面):

基于python語(yǔ)言的tensorflow的‘端到端’的字符型驗(yàn)證碼識(shí)別源碼整理(github源碼分享)

2???關(guān)鍵詞

關(guān)鍵詞:安全,字符圖片,驗(yàn)證碼識(shí)別,OCR,Python,SVM,PIL

3???免責(zé)聲明

本文研究所用素材來(lái)自于某舊Web框架的網(wǎng)站?完全對(duì)外公開(kāi)?的公共圖片資源。

本文只做了該網(wǎng)站對(duì)外公開(kāi)的公共圖片資源進(jìn)行了爬取,?并未越權(quán)?做任何多余操作。

本文在書(shū)寫(xiě)相關(guān)報(bào)告的時(shí)候已經(jīng)?隱去?漏洞網(wǎng)站的身份信息。

本文作者?已經(jīng)通知?網(wǎng)站相關(guān)人員此系統(tǒng)漏洞,并積極向新系統(tǒng)轉(zhuǎn)移。

本報(bào)告的主要目的也僅是用于?OCR交流學(xué)習(xí)?和引起大家對(duì)?驗(yàn)證安全的警覺(jué)?。

4???引言

關(guān)于驗(yàn)證碼的非技術(shù)部分的介紹,可以參考以前寫(xiě)的一篇科普類的文章:

互聯(lián)網(wǎng)安全防火墻(1)--網(wǎng)絡(luò)驗(yàn)證碼的科普

里面對(duì)驗(yàn)證碼的種類,使用場(chǎng)景,作用,主要的識(shí)別技術(shù)等等進(jìn)行了講解,然而并沒(méi)有涉及到任何技術(shù)內(nèi)容。本章內(nèi)容則作為它的?技術(shù)補(bǔ)充?來(lái)給出相應(yīng)的識(shí)別的解決方案,讓讀者對(duì)驗(yàn)證碼的功能及安全性問(wèn)題有更深刻的認(rèn)識(shí)。

5???基本工具

要達(dá)到本文的目的,只需要簡(jiǎn)單的編程知識(shí)即可,因?yàn)楝F(xiàn)在的機(jī)器學(xué)習(xí)領(lǐng)域的蓬勃發(fā)展,已經(jīng)有很多封裝好的開(kāi)源解決方案來(lái)進(jìn)行機(jī)器學(xué)習(xí)。普通程序員已經(jīng)不需要了解復(fù)雜的數(shù)學(xué)原理,即可以實(shí)現(xiàn)對(duì)這些工具的應(yīng)用了。

主要開(kāi)發(fā)環(huán)境:

python3.5

python SDK版本

PIL

圖片處理庫(kù)

libsvm

開(kāi)源的svm機(jī)器學(xué)習(xí)庫(kù)

關(guān)于環(huán)境的安裝,不是本文的重點(diǎn),故略去。

6???基本流程

一般情況下,對(duì)于字符型驗(yàn)證碼的識(shí)別流程如下:

準(zhǔn)備原始圖片素材

圖片預(yù)處理

圖片字符切割

圖片尺寸歸一化

圖片字符標(biāo)記

字符圖片特征提取

生成特征和標(biāo)記對(duì)應(yīng)的訓(xùn)練數(shù)據(jù)集

訓(xùn)練特征標(biāo)記數(shù)據(jù)生成識(shí)別模型

使用識(shí)別模型預(yù)測(cè)新的未知圖片集

達(dá)到根據(jù)“圖片”就能返回識(shí)別正確的字符集的目標(biāo)

7???素材準(zhǔn)備

7.1???素材選擇

由于本文是以初級(jí)的學(xué)習(xí)研究目的為主,要求?“有代表性,但又不會(huì)太難”?,所以就直接在網(wǎng)上找個(gè)比較有代表性的簡(jiǎn)單的字符型驗(yàn)證碼(感覺(jué)像在找漏洞一樣)。

最后在一個(gè)比較舊的網(wǎng)站(估計(jì)是幾十年前的網(wǎng)站框架)找到了這個(gè)驗(yàn)證碼圖片。

原始圖:

放大清晰圖:

此圖片能滿足要求,仔細(xì)觀察其具有如下特點(diǎn)。

有利識(shí)別的特點(diǎn)?:

由純阿拉伯?dāng)?shù)字組成

字?jǐn)?shù)為4位

字符排列有規(guī)律

字體是用的統(tǒng)一字體

以上就是本文所說(shuō)的此驗(yàn)證碼簡(jiǎn)單的重要原因,后續(xù)代碼實(shí)現(xiàn)中會(huì)用到

不利識(shí)別的特點(diǎn)?:

圖片背景有干擾噪點(diǎn)

這雖然是不利特點(diǎn),但是這個(gè)干擾門檻太低,只需要簡(jiǎn)單的方法就可以除去

7.2???素材獲取

由于在做訓(xùn)練的時(shí)候,需要大量的素材,所以不可能用手工的方式一張張?jiān)跒g覽器中保存,故建議寫(xiě)個(gè)自動(dòng)化下載的程序。

主要步驟如下:

通過(guò)瀏覽器的抓包功能獲取隨機(jī)圖片驗(yàn)證碼生成接口

批量請(qǐng)求接口以獲取圖片

將圖片保存到本地磁盤(pán)目錄中

這些都是一些IT基本技能,本文就不再詳細(xì)展開(kāi)了。

關(guān)于網(wǎng)絡(luò)請(qǐng)求和文件保存的代碼,如下:

def downloads_pic(**kwargs):

pic_name = kwargs.get('pic_name', None)

url = 'httand_code_captcha/'

res = requests.get(url, stream=True)

with open(pic_path + pic_name+'.bmp', 'wb') as f: ? ? ? ?for chunk in res.iter_content(chunk_size=1024): ? ? ? ? ? ?if chunk: ?# filter out keep-alive new chunks ? ? ? ? ? ? ? ?f.write(chunk)

? ? ? ? ?f.flush()

?f.close()

循環(huán)執(zhí)行N次,即可保存N張驗(yàn)證素材了。

下面是收集的幾十張素材庫(kù)保存到本地文件的效果圖:

8???圖片預(yù)處理

雖然目前的機(jī)器學(xué)習(xí)算法已經(jīng)相當(dāng)先進(jìn)了,但是為了減少后面訓(xùn)練時(shí)的復(fù)雜度,同時(shí)增加識(shí)別率,很有必要對(duì)圖片進(jìn)行預(yù)處理,使其對(duì)機(jī)器識(shí)別更友好。

針對(duì)以上原始素材的處理步驟如下:

讀取原始圖片素材

將彩色圖片二值化為黑白圖片

去除背景噪點(diǎn)

8.1???二值化圖片

主要步驟如下:

將RGB彩圖轉(zhuǎn)為灰度圖

將灰度圖按照設(shè)定閾值轉(zhuǎn)化為二值圖

image = Image.open(img_path)

imgry = image.convert('L') ?# 轉(zhuǎn)化為灰度圖table = get_bin_table()

out = imgry.point(table, '1')

上面引用到的二值函數(shù)的定義如下:

1234567891011121314? ?def?get_bin_table(threshold=140):????"""????獲取灰度轉(zhuǎn)二值的映射table????:param threshold:????:return:????"""????table?=?[]????for?i?in?range(256):????????if?i threshold:????????????table.append(0)????????else:????????????table.append(1)?????return?table? ?

由PIL轉(zhuǎn)化后變成二值圖片:0表示黑色,1表示白色。二值化后帶噪點(diǎn)的?6937?的像素點(diǎn)輸出后如下圖:

1111000111111000111111100001111100000011

1110111011110111011111011110111100110111

1001110011110111101011011010101101110111

1101111111110110101111110101111111101111

1101000111110111001111110011111111101111

1100111011111000001111111001011111011111

1101110001111111101011010110111111011111

1101111011111111101111011110111111011111

1101111011110111001111011110111111011100

1110000111111000011101100001110111011111

如果你是近視眼,然后離屏幕遠(yuǎn)一點(diǎn),可以隱約看到?6937?的骨架了。

8.2???去除噪點(diǎn)

在轉(zhuǎn)化為二值圖片后,就需要清除噪點(diǎn)。本文選擇的素材比較簡(jiǎn)單,大部分噪點(diǎn)也是最簡(jiǎn)單的那種?孤立點(diǎn),所以可以通過(guò)檢測(cè)這些孤立點(diǎn)就能移除大量的噪點(diǎn)。

關(guān)于如何去除更復(fù)雜的噪點(diǎn)甚至干擾線和色塊,有比較成熟的算法:?洪水填充法 Flood Fill?,后面有興趣的時(shí)間可以繼續(xù)研究一下。

本文為了問(wèn)題簡(jiǎn)單化,干脆就用一種簡(jiǎn)單的自己想的?簡(jiǎn)單辦法?來(lái)解決掉這個(gè)問(wèn)題:

對(duì)某個(gè)?黑點(diǎn)?周邊的九宮格里面的黑色點(diǎn)計(jì)數(shù)

如果黑色點(diǎn)少于2個(gè)則證明此點(diǎn)為孤立點(diǎn),然后得到所有的孤立點(diǎn)

對(duì)所有孤立點(diǎn)一次批量移除。

下面將詳細(xì)介紹關(guān)于具體的算法原理。

將所有的像素點(diǎn)如下圖分成三大類

頂點(diǎn)A

非頂點(diǎn)的邊界點(diǎn)B

內(nèi)部點(diǎn)C

種類點(diǎn)示意圖如下:

其中:

A類點(diǎn)計(jì)算周邊相鄰的3個(gè)點(diǎn)(如上圖紅框所示)

B類點(diǎn)計(jì)算周邊相鄰的5個(gè)點(diǎn)(如上圖紅框所示)

C類點(diǎn)計(jì)算周邊相鄰的8個(gè)點(diǎn)(如上圖紅框所示)

當(dāng)然,由于基準(zhǔn)點(diǎn)在計(jì)算區(qū)域的方向不同,A類點(diǎn)和B類點(diǎn)還會(huì)有細(xì)分:

A類點(diǎn)繼續(xù)細(xì)分為:左上,左下,右上,右下

B類點(diǎn)繼續(xù)細(xì)分為:上,下,左,右

C類點(diǎn)不用細(xì)分

然后這些細(xì)分點(diǎn)將成為后續(xù)坐標(biāo)獲取的準(zhǔn)則。

主要算法的python實(shí)現(xiàn)如下:

def sum_9_region(img, x, y): ? ?"""

9鄰域框,以當(dāng)前點(diǎn)為中心的田字框,黑點(diǎn)個(gè)數(shù)

:param x:

:param y:

:return: ? ?"""

# todo 判斷圖片的長(zhǎng)寬度下限

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 ? ?if y == 0: ?# 第一行

?if x == 0: ?# 左上頂點(diǎn),4鄰域

? ? ?# 中心點(diǎn)旁邊3個(gè)點(diǎn)

? ? ?sum = cur_pixel \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x, y + 1)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x + 1, y)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x + 1, y + 1)) ? ? ? ? ? ?return 4 - sum ? ? ? ?elif x == width - 1: ?# 右上頂點(diǎn)

? ? ?sum = cur_pixel \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x, y + 1)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x - 1, y)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x - 1, y + 1)) ? ? ? ? ? ?return 4 - sum ? ? ? ?else: ?# 最上非頂點(diǎn),6鄰域

? ? ?sum = img.getpixel((x - 1, y)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x - 1, y + 1)) \ ? ? ? ? ? ? ? ? ?+ cur_pixel \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x, y + 1)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x + 1, y)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x + 1, y + 1)) ? ? ? ? ? ?return 6 - sum ? ?elif y == height - 1: ?# 最下面一行

?if x == 0: ?# 左下頂點(diǎn)

? ? ?# 中心點(diǎn)旁邊3個(gè)點(diǎn)

? ? ?sum = cur_pixel \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x + 1, y)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x + 1, y - 1)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x, y - 1)) ? ? ? ? ? ?return 4 - sum ? ? ? ?elif x == width - 1: ?# 右下頂點(diǎn)

? ? ?sum = cur_pixel \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x, y - 1)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x - 1, y)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x - 1, y - 1)) ? ? ? ? ? ?return 4 - sum ? ? ? ?else: ?# 最下非頂點(diǎn),6鄰域

? ? ?sum = cur_pixel \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x - 1, y)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x + 1, y)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x, y - 1)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x - 1, y - 1)) \ ? ? ? ? ? ? ? ? ?+ img.getpixel((x + 1, y - 1)) ? ? ? ? ? ?return 6 - sum ? ?else: ?# y不在邊界

?if x == 0: ?# 左邊非頂點(diǎn)

? ? ?sum = 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 6 - sum ? ? ? ?elif x == width - 1: ?# 右邊非頂點(diǎn)

? ? ?# print('%s,%s' % (x, y))

? ? ?sum = 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 6 - sum ? ? ? ?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

Tips:這個(gè)地方是相當(dāng)考驗(yàn)人的細(xì)心和耐心程度了,這個(gè)地方的工作量還是蠻大的,花了半個(gè)晚上的時(shí)間才完成的。

計(jì)算好每個(gè)像素點(diǎn)的周邊像素黑點(diǎn)(注意:PIL轉(zhuǎn)化的圖片黑點(diǎn)的值為0)個(gè)數(shù)后,只需要篩選出個(gè)數(shù)為?1或者2?的點(diǎn)的坐標(biāo)即為?孤立點(diǎn)?。這個(gè)判斷方法可能不太準(zhǔn)確,但是基本上能夠滿足本文的需求了。

經(jīng)過(guò)預(yù)處理后的圖片如下所示:

對(duì)比文章開(kāi)頭的原始圖片,那些?孤立點(diǎn)?都被移除掉,相對(duì)比較?干凈?的驗(yàn)證碼圖片已經(jīng)生成。

9???圖片字符切割

由于字符型?驗(yàn)證碼圖片?本質(zhì)就可以看著是由一系列的?單個(gè)字符圖片?拼接而成,為了簡(jiǎn)化研究對(duì)象,我們也可以將這些圖片分解到?原子級(jí)?,即:?只包含單個(gè)字符的圖片。

于是,我們的研究對(duì)象由?“N種字串的組合對(duì)象”?變成?“10種阿拉伯?dāng)?shù)字”?的處理,極大的簡(jiǎn)化和減少了處理對(duì)象。

9.1???分割算法

現(xiàn)實(shí)生活中的字符驗(yàn)證碼的產(chǎn)生千奇百怪,有各種扭曲和變形。關(guān)于字符分割的算法,也沒(méi)有很通用的方式。這個(gè)算法也是需要開(kāi)發(fā)人員仔細(xì)研究所要識(shí)別的字符圖片的特點(diǎn)來(lái)制定的。

當(dāng)然,本文所選的研究對(duì)象盡量簡(jiǎn)化了這個(gè)步驟的難度,下文將慢慢進(jìn)行介紹。

使用圖像編輯軟件(PhoneShop或者其它)打開(kāi)驗(yàn)證碼圖片,放大到像素級(jí)別,觀察其它一些參數(shù)特點(diǎn):

可以得到如下參數(shù):

整個(gè)圖片尺寸是 40*10

單個(gè)字符尺寸是 6*10

左右字符和左右邊緣相距2個(gè)像素

字符上下緊挨邊緣(即相距0個(gè)像素)

這樣就可以很容易就定位到每個(gè)字符在整個(gè)圖片中占據(jù)的像素區(qū)域,然后就可以進(jìn)行分割了,具體代碼如下:

def get_crop_imgs(img): ? ?"""

按照?qǐng)D片的特點(diǎn),進(jìn)行切割,這個(gè)要根據(jù)具體的驗(yàn)證碼來(lái)進(jìn)行工作. # 見(jiàn)原理圖

:param img:

:return: ? ?"""

child_img_list = [] ? ?for i in range(4):

?x = 2 + i * (6 + 4) ?# 見(jiàn)原理圖

?y = 0

?child_img = img.crop((x, y, x + 6, y + 10))

?child_img_list.append(child_img) ? ?return child_img_list

然后就能得到被切割的?原子級(jí)?的圖片元素了:

9.2???內(nèi)容小結(jié)

基于本部分的內(nèi)容的討論,相信大家已經(jīng)了解到了,如果驗(yàn)證碼的干擾(扭曲,噪點(diǎn),干擾色塊,干擾線……)做得不夠強(qiáng)的話,可以得到如下兩個(gè)結(jié)論:

4位字符和40000位字符的驗(yàn)證碼區(qū)別不大

純字母

不區(qū)分大小寫(xiě)。分類數(shù)為26

區(qū)分大小寫(xiě)。分類數(shù)為52

純數(shù)字。分類數(shù)為10

數(shù)字和區(qū)分大小寫(xiě)的字母組合。分類數(shù)為62

純數(shù)字?和?數(shù)字及字母組合?的驗(yàn)證碼區(qū)別不大

在沒(méi)有形成?指數(shù)級(jí)或者幾何級(jí)?的難度增加,而只是?線性有限級(jí)?增加計(jì)算量時(shí),意義不太大。

10???尺寸歸一

本文所選擇的研究對(duì)象本身尺寸就是統(tǒng)一狀態(tài):6*10的規(guī)格,所以此部分不需要額外處理。但是一些進(jìn)行了扭曲和縮放的驗(yàn)證碼,則此部分也會(huì)是一個(gè)圖像處理的難點(diǎn)。

11???模型訓(xùn)練步驟

在前面的環(huán)節(jié),已經(jīng)完成了對(duì)單個(gè)圖片的處理和分割了。后面就開(kāi)始進(jìn)行?識(shí)別模型?的訓(xùn)練了。

整個(gè)訓(xùn)練過(guò)程如下:

大量完成預(yù)處理并切割到原子級(jí)的圖片素材準(zhǔn)備

對(duì)素材圖片進(jìn)行人為分類,即:打標(biāo)簽

定義單張圖片的識(shí)別特征

使用SVM訓(xùn)練模型對(duì)打了標(biāo)簽的特征文件進(jìn)行訓(xùn)練,得到模型文件

12???素材準(zhǔn)備

本文在訓(xùn)練階段重新下載了同一模式的4數(shù)字的驗(yàn)證圖片總計(jì):3000張。然后對(duì)這3000張圖片進(jìn)行處理和切割,得到12000張?jiān)蛹?jí)圖片。

在這12000張圖片中刪除一些會(huì)影響訓(xùn)練和識(shí)別的強(qiáng)干擾的干擾素材,切割后的效果圖如下:

13???素材標(biāo)記

由于本文使用的這種識(shí)別方法中,機(jī)器在最開(kāi)始是不具備任何 數(shù)字的觀念的。所以需要人為的對(duì)素材進(jìn)行標(biāo)識(shí),告訴?機(jī)器什么樣的圖片的內(nèi)容是 1……。

這個(gè)過(guò)程叫做?“標(biāo)記”。

具體打標(biāo)簽的方法是:

為0~9每個(gè)數(shù)字建立一個(gè)目錄,目錄名稱為相應(yīng)數(shù)字(相當(dāng)于標(biāo)簽)

人為判定?圖片內(nèi)容,并將圖片拖到指定數(shù)字目錄中

每個(gè)目錄中存放100張左右的素材

一般情況下,標(biāo)記的素材越多,那么訓(xùn)練出的模型的分辨能力和預(yù)測(cè)能力越強(qiáng)。例如本文中,標(biāo)記素材為十多張的時(shí)候,對(duì)新的測(cè)試圖片識(shí)別率基本為零,但是到達(dá)100張時(shí),則可以達(dá)到近乎100%的識(shí)別率

14???特征選擇

對(duì)于切割后的單個(gè)字符圖片,像素級(jí)放大圖如下:

從宏觀上看,不同的數(shù)字圖片的本質(zhì)就是將黑色按照一定規(guī)則填充在相應(yīng)的像素點(diǎn)上,所以這些特征都是最后圍繞像素點(diǎn)進(jìn)行。

字符圖片?寬6個(gè)像素,高10個(gè)像素?,理論上可以最簡(jiǎn)單粗暴地可以定義出60個(gè)特征:60個(gè)像素點(diǎn)上面的像素值。但是顯然這樣高維度必然會(huì)造成過(guò)大的計(jì)算量,可以適當(dāng)?shù)慕稻S。

通過(guò)查閱相應(yīng)的文獻(xiàn)?[2],給出另外一種簡(jiǎn)單粗暴的特征定義:

每行上黑色像素的個(gè)數(shù),可以得到10個(gè)特征

每列上黑色像素的個(gè)數(shù),可以得到6個(gè)特征

最后得到16維的一組特征,實(shí)現(xiàn)代碼如下:

def get_feature(img): ? ?"""

獲取指定圖片的特征值,

1. 按照每排的像素點(diǎn),高度為10,則有10個(gè)維度,然后為6列,總共16個(gè)維度

:param img_path:

:return:一個(gè)維度為10(高度)的列表 ? ?"""

width, height = img.size

pixel_cnt_list = []

height = 10 ? ?for y in range(height):

?pix_cnt_x = 0 ? ? ? ?for x in range(width): ? ? ? ? ? ?if img.getpixel((x, y)) == 0: ?# 黑色點(diǎn)

? ? ? ? ?pix_cnt_x += 1

?pixel_cnt_list.append(pix_cnt_x) ? ?for x in range(width):

?pix_cnt_y = 0 ? ? ? ?for y in range(height): ? ? ? ? ? ?if img.getpixel((x, y)) == 0: ?# 黑色點(diǎn)

? ? ? ? ?pix_cnt_y += 1

?pixel_cnt_list.append(pix_cnt_y) ? ?return pixel_cnt_list

然后就將圖片素材特征化,按照?libSVM?指定的格式生成一組帶特征值和標(biāo)記值的向量文

如何用Python設(shè)計(jì)一個(gè)通過(guò)身份證號(hào)判斷省份的程序?

area={"11":"北京","12":"天津","13":"河北","14":"山西","15":"內(nèi)蒙古","21":"遼寧","22":"吉林","23":"黑龍江","31":"上海","32":"江蘇","33":"浙江","34":"安徽","35":"福建","36":"江西","37":"山東","41":"河南","42":"湖北","43":"湖南","44":"廣東","45":"廣西","46":"海南","50":"重慶","51":"四川","52":"貴州","53":"云南","54":"西藏","61":"陜西","62":"甘肅","63":"青海","64":"寧夏","65":"新疆","71":"臺(tái)灣","81":"香港","82":"澳門","91":"國(guó)外"}

s=input('輸入身份證號(hào)碼:')

t=s[0]+s[1]

print(area[t])

python身份證號(hào)換成***

最近工作中剛好要清洗一批客戶數(shù)據(jù),涉及到身份證號(hào)碼15位和18位的轉(zhuǎn)換,特意研究了下,在這里分享下。

身份證號(hào)碼的構(gòu)成

既然談到了身份證轉(zhuǎn)換,那就需要先了解下證件號(hào)碼的構(gòu)成。

公民身份號(hào)碼是特征組合碼,由 十七位數(shù)字本體碼 和 一位數(shù)字校驗(yàn)碼 組成;

排列順序從左至右依次為:六位數(shù)字地址碼,八位數(shù)字出生日期碼,三位數(shù)字順序碼和一位數(shù)字校驗(yàn)碼。

六位數(shù)字地址碼:表示編碼對(duì)象常住戶口所在縣(市、旗、區(qū))的行政區(qū)劃代碼,按GB/T 2260 的規(guī)定執(zhí)行。

八位數(shù)字出生日期碼:表示編碼對(duì)象出生的年、月、日,按 GB/T 7408 的規(guī)定執(zhí)行。年、月、日代碼之間不用分隔符。某人出生日期為 1995年08月12日,其出生日期碼為 19950812。

三位順序碼:表示在同一地址碼所標(biāo)識(shí)的區(qū)域范圍內(nèi),對(duì)同年、同月、同日出生的人編定的順序號(hào),順序碼的奇數(shù)分配給男性,偶數(shù)分配給女性。

一位校驗(yàn)碼:校驗(yàn)碼按照 ISO 7064:1983.MOD 11-2校驗(yàn)碼計(jì)算出來(lái)的檢驗(yàn)碼。

校驗(yàn)碼計(jì)算方法

1、將前面的身份證號(hào)碼17位數(shù)分別乘以不同的系數(shù)。從第一位到第十七位的系數(shù)分別為: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 ;

2、將這17位數(shù)字和系數(shù)相乘的結(jié)果相加;

3、用加出來(lái)和除以11,看余數(shù)是多少;

4、余數(shù)只可能有0 1 2 3 4 5 6 7 8 9 10這11個(gè)數(shù)字。其分別對(duì)應(yīng)的最后一位身份證的號(hào)碼為 1 0 X 9 8 7 6 5 4 3 2 ;

5、通過(guò)上面得知如果余數(shù)是2,就會(huì)在身份證的第18位數(shù)字上出現(xiàn)羅馬數(shù)字的X。

解決思路

15位轉(zhuǎn)18位:即身份證號(hào)碼的前六位數(shù)字+ '19' + 身份證第六位以后的數(shù)字 + 校驗(yàn)碼

(不要問(wèn)我為什么加19這種白癡(′⊙ω⊙`) @?¥?的問(wèn)題,當(dāng)然是因?yàn)橹挥?9世紀(jì)的人才可能擁有15位的身份證號(hào)啦)

校驗(yàn)碼計(jì)算方法就更簡(jiǎn)單了,將這17位數(shù)字和系數(shù)相乘的結(jié)果相加除以11匹配余數(shù)對(duì)應(yīng)的號(hào)碼即可。

注意:代碼中我用了幾個(gè)變量,在這里拆解講解下。

Ai: 表示第i位置上的身份證號(hào)碼數(shù)字值 Wi: 表示第i位置上的加權(quán)因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2

十七位數(shù)字本體碼加權(quán)求和公式: S = Sum(AiWi), i = 0, … , 16 ,先對(duì)前17位數(shù)字的權(quán)求和

計(jì)算模 Y = mod(S, 11)

通過(guò)模得到對(duì)應(yīng)的校驗(yàn)碼

Y: 0 1 2 3 4 5 6 7 8 9 10

校驗(yàn)碼: 1 0 X 9 8 7 6 5 4 3 2

OK,分析的差不多了,直接看代碼。

怎么用代碼實(shí)現(xiàn)?

# encoding: utf-8

"""

CREATED ON 19-11-05

@AUTHOR: XUSL

"""

WI = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1, ]

VI = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2, ]

DEF GET_VERITY(EIGHTEEN_CARD):

"""

:PARAM EIGHTEEN_CARD:

:RETURN:

"""

AI = []

REMAINING = ''

IF LEN(EIGHTEEN_CARD) == 18:

EIGHTEEN_CARD = EIGHTEEN_CARD[0:-1]

IF LEN(EIGHTEEN_CARD) == 17:

S = 0

FOR I IN EIGHTEEN_CARD:

AI.APPEND(INT(I))

FOR I IN RANGE(17):

S = S + WI[I] * AI[I]

REMAINING = S % 11

RETURN 'X' IF REMAINING == 2 ELSE STR(VI[REMAINING])

DEF UP_TO_EIGHTEEN(FIFTEEN_CARD):

"""

15位轉(zhuǎn)18位

:PARAM FIFTEEN_CARD:

:RETURN:

"""

EIGHTEEN_CARD = FIFTEEN_CARD[0:6] + '19' + FIFTEEN_CARD[6:15]

RETURN EIGHTEEN_CARD + GET_VERITY(EIGHTEEN_CARD)

DEF DOWN_TO_FIFTEEN(EIGHTEEN_CARD):

"""

18位轉(zhuǎn)15位

:PARAM EIGHTEEN_CARD:

:RETURN:

"""

RETURN EIGHTEEN_CARD[0:6] + EIGHTEEN_CARD[8:17]

IF __NAME__ == '__MAIN__':

# 15位轉(zhuǎn)18位

CARD_1 = UP_TO_EIGHTEEN('632123820927051')

PRINT(CARD_1)

# 18位轉(zhuǎn)15位

CARD_2 = DOWN_TO_FIFTEEN('410125199908222000')

PRINT(CARD_2)

當(dāng)然,這只是個(gè)小功能,主要還是想分享下代碼,如果有同樣的處理可以直接用。

總結(jié)

以上所述是小編給大家介紹的使用Python完成15位18位身份證的互轉(zhuǎn)功能,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

用Python校驗(yàn)身份證號(hào)碼真?zhèn)?/h2>

#這個(gè)算法都給了,應(yīng)該比較簡(jiǎn)單吧。我也很菜,隨意寫(xiě)了一個(gè)。異常沒(méi)做,你可以自##己加一下。做一些驗(yàn)證過(guò)濾。不知道隨機(jī)是不是真是隨意隨機(jī),我沒(méi)有按照身份證規(guī)##則做隨機(jī)。是真的隨機(jī)了18位。。。?如果你有規(guī)則,也可以自己寫(xiě)一個(gè)。

import?random

yushu=[x?for?x?in?range(0,11)]?

ma=['1','0','X','9','8','7','6','5','4','3','2','1']

def?yanzheng(nid):

dicma=dict(zip(yushu,ma))

sum=0

for?x,y?in?enumerate(nid[:-1]):

sum+=((2**(18-x-1))%11)*int(y)?#17位對(duì)應(yīng)系數(shù)相乘的和

if?nid[-1]==dicma[sum%11]:?#校驗(yàn)碼對(duì)照

return?'%s?True'%nid

else:

return?'%s?False'%nid

def?readfile(fname):

f=open(fname,'rb')

for?line?in?f.readlines():

print??yanzheng(line.strip())

f.close()

def?randnum():

idstr=''

for?i?in?range(17):?#前17位隨機(jī)

idstr+=str(random.randint(0,9))

idstr+=random.choice(ma)?#最后一位從列表種隨意一個(gè),因?yàn)橛蠿

return?idstr

if?__name__=="__main__":

nid=raw_input('Please?enter?your?ID:?')?#用戶輸入ID,沒(méi)做任何驗(yàn)證

print?yanzheng(nid)??#驗(yàn)證身份證

readfile('id.txt')???#從文件讀出來(lái)?再驗(yàn)證

print?yanzheng(randnum())??#隨機(jī)一個(gè)?在驗(yàn)證

Python中的input()、isinstance()函數(shù)如何使用

Python解釋器內(nèi)置了許多函數(shù),這意味著我們無(wú)需定義,始終可以它們。接下來(lái)和大家一起討論一個(gè)常用的內(nèi)建函數(shù)-input()和isinstance()。

input()

input()函數(shù)讀取用戶輸入,并轉(zhuǎn)換成字符串:

a?=?input()??#?將input()返回的值賦值給a

Python

a????????????#?查看a的值(為字符串'Python')

'Python'

input()函數(shù)可以提供一個(gè)參數(shù),用來(lái)提示用戶:

b?=?input('請(qǐng)輸入你最喜歡的水果:??')???#?給用戶必要的提示

請(qǐng)輸入你最喜歡的水果:??香蕉

b

'香蕉'

需要注意的是,input()函數(shù)返回的值總是字符串,當(dāng)用戶輸入的是數(shù)字也是這樣,所以當(dāng)使用它時(shí)一定要注意:

num?=?input('請(qǐng)輸入一個(gè)數(shù)字:?')

請(qǐng)輸入一個(gè)數(shù)字:?10

num?+?9????????????????????????????#?試圖把num和數(shù)字相加

Traceback?(most?recent?call?last):

File?"",?line?1,?in

TypeError:?must?be?str,?not?int

num

'10'

type(num)???????????????????????????#?查看num的數(shù)字類型

class?'str'

isinstance()

isinstance()函數(shù)用于檢查對(duì)象是否為指定類(或者說(shuō)數(shù)據(jù)類型)的實(shí)例。isintance()的第一個(gè)參數(shù)為一個(gè)對(duì)象,第二個(gè)參數(shù)為要檢查的數(shù)據(jù)類型。

舉個(gè)例子,比如有有一個(gè)變量,你想檢查它是否為數(shù)字類型,可以使用isinstance()函數(shù):

score?=?90

result?=?isinstance(score,?int)

if?result:

...?????print('score為int數(shù)據(jù)類型')

...?else:

...?????print('score不為int數(shù)據(jù)類型')

...

score為int數(shù)據(jù)類型

除了能檢查是否為int類型外,isintance()還能檢查其他數(shù)據(jù)類型(當(dāng)然了),下面是一個(gè)綜合示例:

pi?=?3.14

name?=?'Wang'

complex_num?=?1?+?2j

isinstance(pi,?float)??????????????#?3.14為浮點(diǎn)數(shù)類型

True

isinstance(name,?str)??????????????#?'Wang'為字符串類型

True

isinstance(complex_num,?complex)???#??1?+?2j為復(fù)數(shù)

True

isinstance()還可以驗(yàn)證某個(gè)對(duì)象是否為自定義的類型:

class?Developer:?????????????????????????????#?定義一個(gè)叫做Developer的類

...

...?????def?__init__(self,?name):????????????????#?__init__方法中,需要輸入名字

...?????????self.name?=?name

...?????def?display(self):???????????????????????#?定義了display()方法

...?????????print("Developer:",?self.name,?"-")

...

class?PythonDeveloper(Developer):????????????#?PythonDeveloper類,繼承了Developer類

...

...?????def?__init__(self,?name,?language):

...?????????self.name?=?name

...?????????self.language?=?language

...

...?????def?display(self):????????????????????????#?覆蓋了父類的display方法

...?????????print("Python?Developer:",?self.name,?"language:",?self.language,?"-")

...

dev?=?Developer('Zhang')?????????????????????#?創(chuàng)建一個(gè)Developer對(duì)象

dev.display()????????????????????????????????#?調(diào)用display()方法,以查看該對(duì)象

Developer:?Zhang?-

isinstance(dev,?Developer)???????????????????#?判斷dev是否為Developer類,答案是肯定的

True

isinstance(dev,?PythonDeveloper)?????????????#?判斷dev是否為PythonDeveloper類,當(dāng)然不是

False

python_dev?=?PythonDeveloper('Liu',?'Python')??#?創(chuàng)建一個(gè)PythonDeveloper對(duì)象,注意PythonDeveloper是Developer的子類

python_dev.display()??????????????????????????#?調(diào)用display方法

Python?Developer:?Liu?language:?Python?-

isinstance(python_dev,?Developer)?????????????#?判斷python_dev是否為Developer類,答案是肯定的

True

isinstance(python_dev,?PythonDeveloper)??????#?判斷python是否為PythonDeveloper類,答案也是肯定的

True

關(guān)于Python的基礎(chǔ)問(wèn)題可以看下這個(gè)網(wǎng)頁(yè)的視頻教程,網(wǎng)頁(yè)鏈接,希望我的回答能幫到你。

Python 設(shè)計(jì)一個(gè)函數(shù)產(chǎn)生指定長(zhǎng)度的驗(yàn)證碼 length = len(base_str) - 1 ,這里為什么會(huì)減 1????

random.randint()

取的數(shù)的區(qū)間是前后封閉的。也就是可能會(huì)取到last_pos

如果不減1那么就會(huì)出錯(cuò)的。

all_chars[len(all_chars)]就出錯(cuò)了。

當(dāng)前名稱:python身份驗(yàn)證函數(shù) 身份證校驗(yàn)Python
轉(zhuǎn)載來(lái)于:http://www.chinadenli.net/article42/hgdsec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)云服務(wù)器企業(yè)網(wǎng)站制作全網(wǎng)營(yíng)銷推廣ChatGPT搜索引擎優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名