實驗樓Python破解驗證碼

来源:https://www.cnblogs.com/powerzzjcode/archive/2018/11/03/9899285.html
-Advertisement-
Play Games

本人大二,因為Python結業考試項目,又想要學習機器學習方向,但是由於接觸時間不長,選擇了實驗樓的Python破解驗證碼這個項目作為我的項目, 我在原來的基礎上加了一些代碼用於完善,並且對功能如何實現記錄在此,第一次接觸到圖像識別的項目。 這是項目需要的文件鏈接:https://pan.baidu ...


  本人大二,因為Python結業考試項目,又想要學習機器學習方向,但是由於接觸時間不長,選擇了實驗樓的Python破解驗證碼這個項目作為我的項目,

我在原來的基礎上加了一些代碼用於完善,並且對功能如何實現記錄在此,第一次接觸到圖像識別的項目。

  這是項目需要的文件鏈接:https://pan.baidu.com/s/1qoJ5qvU9idmH0v7dnFkMCw  

  總體思想是將驗證碼變成黑白,然後切割成單字元,再與準備好的訓練集相互比對,將相似度最高的字元輸出。

  第一步,先對一個驗證碼進行處理,,①目標是將圖片儘量簡化成黑白,②然後切割出單字元,對此使用的是PIL的Image庫。

  ①導入圖片,轉換成8位像素的圖片

#載入圖片並且轉換成8位像素
im = Image.open("./captcha.gif")
im.convert("P")

  我們需要知道驗證碼的顏色,拾色器工具是一種方法,但是我們通過數據說話,通過列印直方圖 print(im.histogram()) 可以返回如下列表

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1, 2, 0, 1, 0, 0, 1, 0, 2, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 3, 1, 3, 3, 0, 0, 0, 0, 0, 0, 1, 0, 3, 2, 132, 1, 1, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 1, 0, 1, 0, 0, 8, 1, 0, 0, 0, 0, 1, 6, 0, 2, 0, 0, 0, 0, 18, 1, 1, 1, 1, 1, 2, 365, 115, 0, 1, 0, 0, 0, 135, 186, 0, 0, 1, 0, 0, 0, 116, 3, 0, 0, 0, 0, 0, 21, 1, 1, 0, 0, 0, 2, 10, 2, 0, 0, 0, 0, 2, 10, 0, 0, 0, 0, 1, 0, 625]

  列表每一個元素代表在圖片中含有對應位的顏色的像素的數量。(白色255,黑色是0)

  接下來進行排序

his = im.histogram()
values = {}
#將顏色作為鍵,出現次數作為值,形成字典
for i in range(256):
    values[i] = his[i]
#對字典進行排序,排序根據字典的值(x[0]是字典的鍵),從大到小排序
for j,k in sorted(values.items(),key=lambda x:x[1],reverse = True)[:10]:
    print(j,k)

  即可得到以下

255 625
212 365
220 186
219 135
169 132
227 116
213 115
234 21
205 18
184 15

  220與227是我們所需要的紅色,於是我們可以創建一個相同大小的純白色的圖片,將符合的顏色變為黑色0

 (其實這裡也就表現了這個程式的第一個局限性,顏色要人為判斷,並且每一個字元都要顏色統一)

# 構造一個純白的等大小的圖片im2
im2 = Image.new("P", im.size, 255)
#遍歷載入的圖片,對每個像素點判斷是否符合要求
for x in range(im.size[1]):         #im.size[1]是垂直像素數
    for y in range(im.size[0]):     #im.size[0]是水平像素數
        pix = im.getpixel((y, x))       #獲取每一個像素點的顏色紙
        if pix == 220 or pix == 227:    #判斷是否符合220或者227
            im2.putpixel((y, x), 0)     #符合則變成黑色

  之後用im2.show(),可以看到這個很符合我們的想法

  ②然後我們需要切割出單個字元,實驗樓裡面說:“由於例子比較簡單,我們對其進行縱向切割:”,恕我剛剛接觸時間不長,還不太能瞭解這句話後面的深度

  具體做法就是縱向從左到右“一刀刀往下切”

  一個變數判斷是否切到了黑色的像素點,切到則轉換“刀”為切到字元的狀態並且記錄當前的水平位置,

如果沒有切到黑色像素點,但是“刀”依舊是切到字元的狀態,則重置“刀”為未切到字元的狀態並且當前的記錄水平位置,

第一次記錄的位置到第二次記錄的位置一定有一個字元。

inletter = False  #判斷是否切割到了字元
foundletter = False     #未切到字元的狀態記錄
start = 0       #記錄開始的x值
end = 0          #記錄結束的x值
letters = []    #記錄切割到的字元
#縱向切割記錄數據
for x in range(im2.size[0]):    #遍歷水平的像素點
    for y in range(im2.size[1]): #同一水平值下遍歷垂直的(用刀切)
        pix = im2.getpixel((x, y))  #獲取像素點顏色
        if pix != 255:           #碰到黑色就位切到了
            inletter = True
    # 切到但是刀的狀態是沒有切到,則轉換刀的狀態為切到
    if foundletter == False and inletter == True:
        foundletter = True
        start = x

    #如果上面if沒有成立,則下麵的if不會發生,所以letters一定會記錄到2個不同的值

    #沒有切到但是刀的狀態是切到了,則轉換刀的狀態為未切到
    if foundletter == True and inletter == False:
        foundletter = False
        end = x
        letters.append((start, end))
    #重置為未切到字元
    inletter = False

  列印letters,符合預期

[(6, 14), (15, 25), (27, 35), (37, 46), (48, 56), (57, 67)]

 然後將記錄到的數據,對圖片進行切割

#切割字元
for letter in letters:
    #參數一個四元組,四個元素依次是左上角的x和y值與右下角的x和y值
    im3 = im2.crop((letter[0], 0, letter[1], im.size[1]))

  然後可以遍歷保存im3為.gif格式,可以得到6個圖片                    都是單獨的字元了,至此第一步完成

  接下來就是核心的第二步,怎麼把每一個字元輸出對應的數字?

  首先是實驗樓給出的論文網站http://ondoc.logand.com/d/2697/pdf,

  “也說了這個這個方法的優缺點:

  • 不需要大量的訓練迭代
  • 不會訓練過度
  • 你可以隨時加入/移除錯誤的數據查看效果
  • 很容易理解和編寫成代碼
  • 提供分級結果,你可以查看最接近的多個匹配
  • 對於無法識別的東西只要加入到搜索引擎中,馬上就能識別了。

  當然它也有缺點,例如分類的速度比神經網路慢很多,它不能找到自己的方法解決問題等等。”

  然後實驗樓只是簡單的介紹了一下原理,並未詳細說明,為此我通讀了整篇論文,來說說我的一點理解。

  有1篇講貓和狗和鼠的文章,但是我想知道這篇文章主要講的是哪個動物,為此我將“貓”,“狗”,“鼠”這幾個特征性的單詞作為我的重點關註對象,並建立一個一個三維空間,x軸對應“貓”這個單詞出現的次數,同理y軸對應“狗”,z軸對應“鼠”。首先先用於第一篇文章,“貓”出現一次,x就加1,“狗”出現一次,y就加1,“鼠”出現一次,z就加1,那麼整篇文章遍歷完了,就一定在三維空間中有一個向量(x1,y1,z1)對應出現次數,然後將這個向量投影在x,y,z軸的值,最大的值對應的軸就是這篇文章出現最多的單詞了,也應該是這篇文章主要講的動物了。

  在x軸上的投影為在向量大小為定值時,夾角越小,餘弦越大,則投影越大,所以我們不用計算出具體的投影的值,問題轉化成了求夾角的餘弦即可。

  兩向量的夾角公式帶入相應的數值即可得到即可知道和x軸夾角,同理與y軸夾角與z軸夾角之後只需要找出最大的餘弦值,對應的字元就是最相關的。

  這是基本矢量空間搜索引擎理論的含義,然後將這個方法用於圖片,會變得更加的複雜,但是核心思想並未改變。

  然後我們照著改一下。

  有1個未知字元(字母或者數字)的圖片,但是我想知道這個字元講的是哪個字元,為此我找了26+10個對應不同字元的圖片作為我的已知的標準,將標準圖片的每個像素點的顏色作為我的重點關註對象,再並建立一個n維向量,每一維則對應一個標準圖片的像素點位置,我只要把未知圖片每一個像素點的顏色值值代入,以及標準圖片每一個像素點的顏色值代入,最後一定有2個向量表示未知圖片和這一個標準圖片,然後求未知圖片與這一標準圖片的向量的夾角的餘弦值,然後用同樣方法做36遍,再按照相似度從大到小排序即可,最大餘弦值的對應的已知字元應該最接近。這有個要求就是我們的標準的像素點的數量和未知的圖片像素點數量要想接近,這應該涉及到了數據預處理的問題,我還沒有學,但是我覺得如果像素點數量差距變大,會很影響判斷的,所以以下,我們當我們的數據都很好的預處理了。

  總的來說,和原本的區別就是我們的重點關註對象變多了,以及我們的標準也不只是單單的坐標軸了,標準也變成一個向量。綜上我們一共需要完成①圖片變成矢量②計算矢量大小③計算夾角

  ①圖片準換成矢量,我們定義成為一個函數,返回一個字典,鍵就是像素點位置(0,1,2,3...),值就是像素點顏色(0,255)

#圖片轉換成矢量,字典化圖片
def buildvector(im):#參數是字元的圖片
    d1 = {}         #字典記錄像素點位置和對應的顏色
    count =0        #用來增加像素點位置
    for i  in im.getdata(): #i就是從0開始對應的顏色值
        d1[count] = i   #把顏色值作為值加入字典
        count +=1       
    return d1       #返回{像素點位置:顏色}的字典

  ②計算矢量大小以及③計算夾角同時放在一個類裡面

import math
#
比較矢量相似度的類 class VectorCompare: #計算矢量大小,即求餘弦的分母的元素 def magnitude (self,concordance): total = 0 for word,count in concordance.items():#word像素點位置,count對應的顏色(0或255) total += count**2 return math.sqrt(total) #求出向量的模的大小 #計算矢量的夾角 def relation(self,concordance1,concordance2): #輸入兩個字典化圖片 topvalue =0 #求餘弦公式的分子 for word,count in concordance1.items(): #需要很好的數據預處理 if word in concordance2: # 每一維度(像素點),兩向量的顏色值(0或255)相乘,求出餘弦公式分子 topvalue += count *concordance2[word] all_magnitude = self.magnitude(concordance1)*self.magnitude(concordance2) #求餘弦公式的分母 relevance = topvalue/all_magnitude #求出餘弦 return relevance #返回相關性

  之後就是要用圖片轉換矢量函數先把我的標準訓練集先完成,而標準訓練集就是iconset文件夾下的文件,我們需要從iconset文件夾里把每一個圖片和文件夾的名字一一對應上,所以我們需要用os庫來獲取文件名

#訓練集名字
iconset = ['0','1','2','3','4','5','6','7','8','9',
           'a','b','c','d','e','f','g','h','i','j',
           'k','l','m','n','o','p','q','r','s','t',
           'u','v','w','x','y','z']

#載入訓練集
imageset = []   #[{正確名字1:[字典化圖片]}, {正確名字2:[字典化圖片]}, {正確名字3:[字典化圖片]}。。。]
#字典化iconset裡面圖片
for letter in iconset:  #遍歷iconset所有要訓練的名字
    for img in os.listdir("./iconset/%s"%(letter)): #遍歷所有iconset裡面的文件夾
        temp = []       #列表用來記錄字典化圖片
        if img != "Thumbs.db" and img!= ".DS_Store":    #不需要訓練的文件
            temp.append(buildvector(Image.open("./iconset/%s/%s"%(letter,img))))  #生成字典化圖片
        imageset.append({letter:temp})  #將訓練的名字和字典化圖片再對應

  最後一步,把我們之前切的im3逐一遍歷,再排序出相似度最高的對應的正確名字,最後列印出所有字元串

#判斷單個字元的相似度
str = ""          #列印字元串
for letter in letters:
    im3 = im2.crop((letter[0], 0, letter[1], im.size[1]))
    guess = []  #記錄和所有訓練集的數據,用來排序
    for image in imageset:  #和所有訓練集的數據進行遍歷
        for x, y in image.items():  #x是正確名字,y是對應的[字典化圖片]
            if len(y) != 0: #y不為空,除去是Thumbs.db和.DS_Store訓練出來的空列表
                guess.append((v.relation(y[0], buildvector(im3)), x))#y[0]就是字典化圖片
    guess.sort(reverse=True) #從大到小排序
    str += "{}".format(guess[0][1]) #相似度最高的字元加到字元串里
print(str)  #列印

  列印結果為

7s9t9j

  這一個到此為止成功。實驗樓的項目至此結束

  所有代碼

from PIL import Image
import math
import os

#比較矢量相似度的類
class VectorCompare:
    #計算矢量大小,即求餘弦的分母的元素
    def magnitude (self,concordance):
        total = 0
        for word,count in concordance.items():#word像素點位置,count對應的顏色(0或255)
            total += count**2
        return math.sqrt(total)         #求出向量的模的大小

    #計算矢量的夾角
    def relation(self,concordance1,concordance2):   #輸入兩個字典化圖片
        topvalue =0                                #求餘弦公式的分子
        for word,count in concordance1.items():     #需要很好的數據預處理
            if word in concordance2:
                # 同一維度(像素點),兩向量的顏色值(0或255)相乘,求出餘弦公式分子
                topvalue += count *concordance2[word]
        all_magnitude = self.magnitude(concordance1)*self.magnitude(concordance2)   #求餘弦公式的分母
        relevance = topvalue/all_magnitude      #求出餘弦
        return relevance            #返回相關性

#圖片轉換成矢量,字典化圖片
def buildvector(im):#參數是字元的圖片
    d1 = {}         #字典記錄像素點位置和對應的顏色
    count =0        #用來增加像素點位置
    for i  in im.getdata(): #i就是從0開始對應的顏色值
        d1[count] = i   #把顏色值作為值加入字典
        count +=1
    return d1       #返回{像素點位置:顏色}的字典

#實例化
v = VectorCompare()
#訓練集名字
iconset = ['0','1','2','3','4','5','6','7','8','9',
           'a','b','c','d','e','f','g','h','i','j',
           'k','l','m','n','o','p','q','r','s','t',
           'u','v','w','x','y','z']

#載入訓練集
imageset = []   #[{正確名字1:[字典化圖片]}, {正確名字2:[字典化圖片]}, {正確名字3:[字典化圖片]}。。。]
#字典化iconset裡面圖片
for letter in iconset:  #遍歷iconset所有要訓練的名字
    for img in os.listdir("./iconset/%s"%(letter)): #遍歷所有iconset裡面的文件夾
        temp = []       #列表用來記錄字典化圖片
        if img != "Thumbs.db" and img!= ".DS_Store":    #不需要訓練的文件
            temp.append(buildvector(Image.open("./iconset/%s/%s"%(letter,img))))  #生成字典化圖片
        imageset.append({letter:temp})  #將訓練的名字和字典化圖片再對應


# 載入圖片並且轉換成8位像素
im = Image.open("./captcha.gif")
im.convert("P")
# 構造一個純白的等大小的圖片im2
im2 = Image.new("P", im.size, 255)
# 遍歷載入的圖片,對每個像素點判斷是否符合要求
for x in range(im.size[1]):  # im.size[1]是垂直像素數
    for y in range(im.size[0]):  # im.size[0]是水平像素數
        pix = im.getpixel((y, x))  # 獲取每一個像素點的顏色紙
        if pix == 220 or pix == 227:  # 判斷是否符合220或者227
            im2.putpixel((y, x), 0)  # 符合則變成黑色

inletter = False  # 判斷是否切割到了字元
foundletter = False  # 未切到字元的狀態記錄
start = 0  # 記錄開始的x值
end = 0  # 記錄結束的x值
letters = []  # 記錄切割到的字元
# 縱向切割記錄數據
for x in range(im2.size[0]):  # 遍歷水平的像素點
    for y in range(im2.size[1]):  # 同一水平值下遍歷垂直的(用刀切)
        pix = im2.getpixel((x, y))  # 獲取像素點顏色
        if pix != 255:  # 碰到黑色就位切到了
            inletter = True
    # 切到但是刀的狀態是沒有切到,則轉換刀的狀態為切到
    if foundletter == False and inletter == True:
        foundletter = True
        start = x

    # 如果上面if沒有成立,則下麵的if不會發生,所以letters一定會記錄到2個不同的值

    # 沒有切到但是刀的狀態是切到了,則轉換刀的狀態為未切到
    if foundletter == True and inletter == False:
        foundletter = False
        end = x
        letters.append((start, end))
    # 重置為未切到字元
    inletter = False

# 判斷單個字元的相似度
str = ""  # 列印字元串
for letter in letters:
    im3 = im2.crop((letter[0], 0, letter[1], im.size[1]))
    guess = []  # 記錄和所有訓練集的數據,用來排序
    for image in imageset:  # 和所有訓練集的數據進行遍歷
        for x, y in image.items():  # x是正確名字,y是對應的[字典化圖片]
            if len(y) != 0:  # y不為空,除去是Thumbs.db和.DS_Store訓練出來的空列表
                guess.append((v.relation(y[0], buildvector(im3)), x))  # y[0]就是字典化圖片
    guess.sort(reverse=True)  # 從大到小排序
    str += "{}".format(guess[0][1])  # 相似度最高的字元加到字元串里

  

  之後便要對所有的examples文件夾下的驗證碼都進行訓練,看看準確度如何

  從載入圖片到最後的判斷字元都放入一個for迴圈語句當中

for listname in os.listdir("./examples"):

  以及驗證碼圖片的載入也要修改為

    if listname != "Thumbs.db" and listname != ".DS_Store":
        im = Image.open("./examples/%s" % (listname))
        im.convert("P")

  下麵的所有代碼都要這個if條件下才能實施,全部再縮進一行

  當我再次列印輸出的時候顯示的驗證碼結果是

0q1dp0
0q3tje
24alb0p
47j17b
4wwfa
5dwvo
5t0qh
75rc1qp
7s9t9j
bibfkf
bf5te
9f2luc
9tmxf
9to1tkp
akfvav
aro2hz
b17lzh
b3rk8h
b3ufl9
pbmk5jx
2mybt
cw0qy
cfyrg
eb0qy3
etg5z
fnt5x
phd0qli
ivusjv
jfte2
zttiq
k0qg4l
k6e2ir
w0qlk
w7k5z
l9felg
lz73a7
t1sge
n67dmb
nlrzo7
tmisv
f15jnd
fmiunq
qfwix9
r2lvkd
r6r12e
718ft
t6khw
ibrjc
puc1rdk
v63gde
7f54eg
xfnrsn

  有長有短,但是驗證碼的長度應當是6個字元,對錯我也並不知曉,所以我開始著手準備

我在迴圈前加了一系列變數用來記錄我所疑惑的

success =0            #記錄正確匹配個數
fail = 0                #記錄失敗的個數
success_name_list=[]        #記錄正確匹配的名字
fail_name_list =[]          #記錄失敗的名字
wrong_length_name = []        #記錄失敗的錯誤長度的名字
wrong_letter_count_dict= {}       #記錄失敗的對應的字母錯誤並累加記錄次數
correct_name_list = []          #記錄錯誤所對應的正確名字,列表下標對應,對比容易

  然後我在每一次迴圈剛開始的時候都記錄下當前驗證碼的正確名字,也就是圖片名

correct_name = listname[:6]  # 記錄正確的文件名 ,用來判斷是否正確

  然後就是對結果str進行判斷,並記錄相關數據

        if str == correct_name: #正確
            success += 1        #正確次數加1
            success_name_list.append(str)   #記錄正確的名字
        else:
            fail +=1    #錯誤次數加1
            fail_name_list.append(str)  #記錄錯誤名字
            correct_name_list.append(correct_name)  #同時記錄對應的正確名字用來進一步分析

  最後就是將相關數據彙總分析,我盡我能力全分析了,過程具體註釋也就不詳細寫了,

count =0 #錯誤名字列表和對應的正確名字的下標一一對應
#統計出錯誤的原因
for letters in fail_name_list:
    # 長度不統一
    if len(letters) != len(correct_name_list[count]):
        wrong_length_name.append(letters)
        count+=1

    #長度統一,但是識別錯誤
    else:
        index =0
        for letter in letters:
            if letter != correct_name_list[count][index]:
                wrong_letter_count_dict[letter] = wrong_letter_count_dict.get(letter,0)+1
                index+=1
            else:
                index+=1
        count+=1


success_rate = success/(success+fail)       #成功率
#列印總數,成功和失敗的數量,以及成功率
print("total count = {}\n"
      "success = {}, failed = {} \n"
       " success_rate = {}\n".format(success+fail,success,fail,success_rate))

#列印成功的驗證碼的名字
print("Success Trainning name:")
for i in range(len(success_name_list)):
    print(success_name_list[i])


wrong_length_count = len(wrong_length_name)                 #去除長度識別錯誤的數量
success_rate = success/(success+fail-wrong_length_count)    #去除長度錯誤的圖片後的成功率
#列印錯誤長度的驗證碼的數量
print("\nWrong Length count:{}".format(wrong_length_count))
print("total count without wrong length= {}\n"
      "success = {}, failed = without wrong length = {} \n"
       "success_rate without wrong length= {:.4f}\n".format(success+fail-wrong_length_count,
                                                         success,
                                                         fail-wrong_length_count,
                                                         success_rate))

#將字母識別錯誤>1的輸出,用來表示標準樣本的錯誤
wrong_letter_count_list = sorted(wrong_letter_count_dict.items(),
                                 key = lambda x:x[1],
                                 reverse =True)
for letter in wrong_letter_count_list:
    if letter[1] >1:
        print("Need more {} to train".format(letter[0]))

  最後運行一下

total count = 52
success = 13, failed = 39 
 success_rate = 0.25

Success Trainning name:
0q3tje
47j17b
7s9t9j
9f2luc
b3rk8h
b3ufl9
k6e2ir
nlrzo7
qfwix9
r2lvkd
r6r12e
v63gde
xfnrsn

Wrong Length count:25
total count without wrong length= 27
success = 13, failed = without wrong length = 14 
success_rate without wrong length= 0.4815

Need more f to train
Need more b to train
Need more v to train
Need more 7 to train

  其他的數據不多說,我後來列印了錯誤字元的字典,發現“f”錯了4次我很好奇為什麼,然後打開訓練集一看

好嘛,根本沒有小寫“f”的訓練集,網上的訓練集也不靠譜啊

  最後總體說說我有可能需要改進的地方,首先是之前說到的顏色,要我手動輸入,而且還必須統一顏色,弄得不好還可能要多出一個字元,可是如果要解決這個要k鄰近?或者涉及到神經網路了,我才剛看了一點書。。。路漫漫其修遠兮。其次,根據上面的數據可以看到很多辨別失敗的是因為長度辨識錯誤,也就是字元的像素點重合在一起了,會把兩個字元合成一個字元判斷,我現在想不到能用什麼辦法來解決這個問題。智商不夠用。

  真正的最後附上我的全部代碼

from PIL import Image
import math
import os


#比較矢量相似度的類
class VectorCompare:
    #計算矢量大小,即求餘弦的分母的元素
    def magnitude (self,concordance):
        total = 0
        for word,count in concordance.items():#word像素點位置,count對應的顏色(0或255)
            total += count**2
        return math.sqrt(total)         #求出向量的模的大小

    #計算矢量的夾角
    def relation(self,concordance1,concordance2):   #輸入兩個字典化圖片
        topvalue =0                                #求餘弦公式的分子
        for word,count in concordance1.items():     #需要很好的數據預處理
            if word in concordance2:
                # 同一維度(像素點),兩向量的顏色值(0或255)相乘,求出餘弦公式分子
                topvalue += count *concordance2[word]
        all_magnitude = self.magnitude(concordance1)*self.magnitude(concordance2)   #求餘弦公式的分母
        relevance = topvalue/all_magnitude      #求出餘弦
        return relevance            #返回相關性

#圖片轉換成矢量,字典化圖片
def buildvector(im):#參數是字元的圖片
    d1 = {}         #字典記錄像素點位置和對應的顏色
    count =0        #用來增加像素點位置
    for i  in im.getdata(): #i就是從0開始對應的顏色值
        d1[count] = i   #把顏色值作為值加入字典
        count +=1
    return d1       #返回{像素點位置:顏色}的字典

#實例化
v = VectorCompare()
#訓練集名字
iconset = ['0','1','2','3','4','5',
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • el-upload組件預設情況下上傳多少個文件就會請求多少次上傳介面,如何一次上傳多個文件而不必多次請求上傳介面呢?直接看代碼 html <el-upload :action="actionUrl" :auto-upload="false" :multiple="true" :file-list=" ...
  • 1.安裝jquery npm install jquery --save-dev 2.打開配置文件webpack.base.conf.js 加入'jquery': path.resolve(__dirname, '../node_modules/jquery/src/jquery') //引入jqu ...
  • 今天刷到一道面試題,["1", "2", "3"].map(parseInt)返回的結果是什麼呢?可能大家第一個想到的是 [1,2,3],但是,我可以明確的告訴你,這是結果錯的!真正的答案是 [1,NaN,NaN] 由於map()接收的回調函數可以有3個參數:callback(currentValu ...
  • 對CAP原理的理解 CAP原理按照定義,指的是C(Consistency)一致性,A(Availability)可用性,P(Partition tolerance)分區容錯性在一個完整的電腦系統中三種特性不能同時得到完全滿足。 Consistency((強)一致性):指的是在同一時間點,所有的數據 ...
  • 在某些情況下,登錄流程由一個OpenID提供者或其他方發起,而不是依賴方(RP)。在這種情況下,發起者重定向到RP在發起登錄終結點,RP的請求驗證請求發送到指定的OP。這個發起登錄終結點可以在RP深度鏈接,而不是預設的登錄頁面。RPs支持OpenID Connect Dynamic Client R ...
  • 1 django.shortcuts import render,HttpResponse 2 from app01.models import * 3 # Create your views here. 4 5 def index(request): 6 return render(request... ...
  • ...
  • ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...