1. python 驗證碼 怎樣去掉干擾線

如果是想讓代碼識別的話,要看驗證碼的復雜程度了,如果比較簡單,使用圖像處理說不定可以解決(我不會,不過網上應該有資料,就算沒有python的,其他語言的也有),但是如果是復雜的,建議你把驗證碼下載下來,如果有圖形界面,就在界面中顯示...

2. 如何利用Python做簡單的驗證碼識別

1摘要

驗證碼是目前互聯網上非常常見也是非常重要的一個事物,充當著很多系統的防火牆功能,但是隨時OCR技術的發展,驗證碼暴露出來的安全問題也越來越嚴峻。本文介紹了一套字元驗證碼識別的完整流程,對於驗證碼安全和OCR識別技術都有一定的借鑒意義。

然後經過了一年的時間,筆者又研究和get到了一種更強大的基於CNN卷積神經網路的直接端到端的驗證識別技術(文章不是我的,然後我把源碼整理了下,介紹和源碼在這裡面):

基於python語言的tensorflow的『端到端』的字元型驗證碼識別源碼整理(github源碼分享)

2關鍵詞

關鍵詞:安全,字元圖片,驗證碼識別,OCR,Python,SVM,PIL

3免責聲明

本文研究所用素材來自於某舊Web框架的網站完全對外公開的公共圖片資源。

本文只做了該網站對外公開的公共圖片資源進行了爬取,並未越權做任何多餘操作。

本文在書寫相關報告的時候已經隱去漏洞網站的身份信息。

本文作者已經通知網站相關人員此系統漏洞,並積極向新系統轉移。

本報告的主要目的也僅是用於OCR交流學習和引起大家對驗證安全的警覺。

4引言

關於驗證碼的非技術部分的介紹,可以參考以前寫的一篇科普類的文章:

互聯網安全防火牆(1)--網路驗證碼的科普

裡面對驗證碼的種類,使用場景,作用,主要的識別技術等等進行了講解,然而並沒有涉及到任何技術內容。本章內容則作為它的技術補充來給出相應的識別的解決方案,讓讀者對驗證碼的功能及安全性問題有更深刻的認識。

5基本工具

要達到本文的目的,只需要簡單的編程知識即可,因為現在的機器學習領域的蓬勃發展,已經有很多封裝好的開源解決方案來進行機器學習。普通程序員已經不需要了解復雜的數學原理,即可以實現對這些工具的應用了。

主要開發環境:

  • python3.5

  • python SDK版本

  • PIL

  • 圖片處理庫

  • libsvm

  • 開源的svm機器學習庫

  • 關於環境的安裝,不是本文的重點,故略去。

    6基本流程

    一般情況下,對於字元型驗證碼的識別流程如下:

  • 准備原始圖片素材

  • 圖片預處理

  • 圖片字元切割

  • 圖片尺寸歸一化

  • 圖片字元標記

  • 字元圖片特徵提取

  • 生成特徵和標記對應的訓練數據集

  • 訓練特徵標記數據生成識別模型

  • 使用識別模型預測新的未知圖片集

  • 達到根據「圖片」就能返回識別正確的字元集的目標

  • 7素材准備

    7.1素材選擇

    由於本文是以初級的學習研究目的為主,要求「有代表性,但又不會太難」,所以就直接在網上找個比較有代表性的簡單的字元型驗證碼(感覺像在找漏洞一樣)。

    最後在一個比較舊的網站(估計是幾十年前的網站框架)找到了這個驗證碼圖片。

    原始圖:

  • def get_feature(img): """

  • 獲取指定圖片的特徵值,

  • 1. 按照每排的像素點,高度為10,則有10個維度,然後為6列,總共16個維度

  • :param img_path:

  • :return:一個維度為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: # 黑色點

  • 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: # 黑色點

  • pix_cnt_y += 1


  • pixel_cnt_list.append(pix_cnt_y) return pixel_cnt_list

  • 然後就將圖片素材特徵化,按照libSVM指定的格式生成一組帶特徵值和標記值的向量文

3. 怎麼讓python單元測試setup只執行一次

怎麼讓python單元測試setup只執行一次
看上去不怎麼難,沒有干擾線沒有粘連沒有扭曲.但我還回是沒答能用pytesser直接將它識別出來,因為當中有噪點和其他背景雜訊的存在.我的工作就是去掉這些討厭的東西 先介紹一下,我們的工具: 1.Pytesser它是基於一個c語言實現名為tesser的識別工具的pyth...

題主在程序中輸入驗證碼,主要是想盡量模模擬人的搜索,結果發現所有cookie是一樣的,無需做這一步驗證碼的輸入,如果是這樣的話,無需驗證碼。另外,按題主的代碼來看,題主只要比較一下輸入驗證碼之前和之後的cookie,如果沒有差別,就去掉驗證碼處理。

4. 如何用python搞定驗證碼中的噪點

看上去不怎麼難,沒有干擾線沒有粘連沒有扭曲.但我還是沒能用pytesser直接將它識別出來,因為當中有噪點和其他背景雜訊的存在.我的工作就是去掉這些討厭的東西
先介紹一下,我們的工具:
1.Pytesser它是基於一個c語言實現名為tesser的識別工具的python封裝.可惜比較笨,只能做最簡單的識別而且不認識漢字
2.Requests它是我們喜歡寫爬蟲的孩子的最愛,提供人性化的介面,代價是失去了一點效率(寫python就別考慮效率啦)
3.BeautifulSoup它和Requests是一對好機油,讓提取文檔中所需的內容變成一件簡單的事情
4.PIL它是今天的主角,PIL是專門用作圖像處理的庫,很好很強大.熟練的人甚至可以用它來P圖
如何寫爬蟲去實現模擬登錄此處不細說,下面說說怎麼解決驗證碼識別
解決思路如下:
1.先用PIL對圖像做一次圖像增強,因為原圖中數字的邊緣和背景中的雜訊並不是太分明,做了增強之後能將兩者分離.如果不分離,可能會在去噪點的時候導致數字中有部分會缺失
im = Image.open("randomimage/randomImage11.jpg")
im = ImageEnhance.Sharpness(im).enhance(3)參數為3是經過實驗之後感覺比較理想的值,太強不好,太弱也不好
2.做完預處理之後,就是去背景雜訊了.背景雜訊指的是背景中各種明暗變換的色塊,肉眼也許不會注意到這個.但是它的存在會給識別帶來影響.我最初的做法是將圖像轉換為只有黑白兩色,這樣自然就將雜訊轉換成了噪點.
效果如圖
但我希望能去掉噪點,成為這樣

最先想到的是種子染色法 ,什麼是種子染色法請參看這個鏈接
為了防止壞鏈,此處做部分轉載
種子染色法英文叫做Flood Fill ,實際上Flood Fill這個名稱更貼切一點,因為這個方法作用在一個圖的結點上時恰似洪水一樣「淹沒」與之相連的其他結點並以相同的方式蔓延出去,這個方法通常用於計算一個圖的極大連通子圖(這里的「圖」是圖論的概念)。設想一個無向圖,我們從這個圖中一個未標號(「標號」可以理解為「染色」)的結點開始,將此結點和從這個結點出發可達的所有結點都賦予相同的標號(染上相同的顏色),那麼我們就得到了這些被標號的結點所組成的一個極大連通子圖,搜索下一個未標號的結點並重復上述過程我們便可以找到所有的極大連通子圖。「染色」的過程可以用DFS或者BFS實現,如果結點數為V,邊數為E,因為我們在Flood Fill過程中「造訪」每個結點兩次,「造訪」每條邊兩次,所以得到所有極大連通子圖的時間復雜度為o(V+E) 。
來自Wikipedia的一個示例:

想像每個白色方塊為圖中的結點,相鄰的方塊(上下左右)有邊相連,那麼這個圖就有三個極大連通子圖,這演示了Flood Fill查找其中一個極大連通子圖的過程。
在這是借要用種子染色法計算每塊的面積,然後把小體積的塊當作噪點去除.
代碼在這

def check(j,i):
try:
if pix[j,i] == 0 and matrix[j][i] != -1:
return True
else:
return False
except:
return False

def juli(r,s):
return abs(r[0]-s[0])+abs(r[1]-s[1])+abs(r[2]-s[2])

for i in range(w):
for j in range(h):
r = [0,0,0]
s = [0,0,0]
if pix[j,i] == 0:
if check(j-1,i):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j-1,i))
print r
print s
print "-"*55
if juli(r,s) <=l:
matrix[j][i] = matrix[j-1][i]
maps[str(matrix[j][i])]+=1
elif check(j-1,i-1):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j-1,i-1))
if juli(r,s) <=l:
matrix[j][i] = matrix[j-1][i-1]
maps[str(matrix[j][i])]+=1
elif check(j,i-1):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j-1,i))
if juli(r,s) <=l:
matrix[j][i] = matrix[j][i-1]
maps[str(matrix[j][i])]+=1
elif check(j+1,i+1):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j+1,i+1))
if juli(r,s) <=l:
matrix[j][i] = matrix[j+1][i+1]
maps[str(matrix[j][i])]+=1
elif check(j,i+1):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j,i+1))
if juli(r,s) <=l:
matrix[j][i] = matrix[j][i+1]
maps[str(matrix[j][i])]+=1
elif check(j-1,i+1):
pr[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j-1,i+1))
if juli(r,s) <=l:
matrix[j][i] = matrix[j-1][i+1]
maps[str(matrix[j][i])]+=1
elif check(j+1,i-1):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j+1,i-1))
if juli(r,s) <=l:
matrix[j][i] = matrix[j+1][i-1]
maps[str(matrix[j][i])]+=1
elif check(j+1,i):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j+1,i))
if juli(r,s) <=l:
matrix[j][i] = matrix[j+1][i]
maps[str(matrix[j][i])]+=1
else:
n+=1
maps[str(n)]=1
matrix[j][i] = n
for i in range(w):
for j in range(h):
if matrix[j][i]!=-1 and maps[str(matrix[j][i])]<=2:
im.putpixel((j,i),255)View Code

結果呢,不是很理想因為這個體積參數設小了,噪點沒去干凈,設大了數字部分可能也去了一小塊.最重要的是這里噪點的大小不是很規律,很難找到一個不錯的面積參數.
失敗只是暫時的,經過觀察發現背景雜訊顏色明顯比數字要淺的多.這也意味著它的RGB值要比數字小的多,通過分析RGB值能去掉大部分雜訊,剩下來的噪點可以再通過種子染色法處理.也就是說,分別在兩張圖片(分別是黑白和彩色)上獲取信息,在一張圖片上做處理最後做識別
核心代碼在這
r[0],r[1],r[2] = im2.getpixel((j,i))
if r[0]+r[1]+r[2]>=400 or r[0]>=250 or r[1]>=250 or r[2]>=250 :
im2.putpixel((j,i),(255,255,255)) 至此,本次識別的問題就搞定啦,成功率在50%以上基本滿足介面的需求

5. 請教生成如圖驗證碼的python演算法

def gene_text():
source = list(string.letters)
for index in range(0,10):
source.append(str(index))
return ''.join(random.sample(source,number))#number是生成驗證碼的位數
然後我們要創建一個圖片,寫入字元串,需要說明的這裡面的字體是不同系統而定,如果沒有找到系統字體路徑的話,也可以不設置
def gene_code():
width,height = size #寬和高
image = Image.new('RGBA',(width,height),bgcolor) #創建圖片
font = ImageFont.truetype(font_path,25) #驗證碼的字體和字體大小
draw = ImageDraw.Draw(image) #創建畫筆
text = gene_text() #生成字元串
font_width, font_height = font.getsize(text)
draw.text(((width - font_width) / number, (height - font_height) / number),text,
font= font,fill=fontcolor) #填充字元串
接下來,我們要在圖片上畫幾條干擾線

#用來繪制干擾線
def gene_line(draw,width,height):
begin = (random.randint(0, width), random.randint(0, height))
end = (random.randint(0, width), random.randint(0, height))
draw.line([begin, end], fill = linecolor)
最後創建扭曲,加上濾鏡,用來增強驗證碼的效果。
image = image.transform((width+20,height+10), Image.AFFINE, (1,-0.3,0,-0.1,1,0),Image.BILINEAR) #創建扭曲
image = image.filter(ImageFilter.EDGE_ENHANCE_MORE) #濾鏡,邊界加強
image.save('idencode.png') #保存驗證碼圖片

6. python 驗證碼加時間戳的功能是怎麼實現的

驗證碼要成功顯示就必須要有一個驗證碼生成器,所以就要寫一個驗證碼生成器。我在app中新建了一個py文件check_coed.py文件,這就是驗證碼生成器。代碼如下
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter

_letter_cases = "abcdefghjkmnpqrstuvwxy" # 小寫字母,去除可能幹擾的i,l,o,z
_upper_cases = _letter_cases.upper() # 大寫字母
_numbers = ''.join(map(str, range(3, 10))) # 數字
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))

def create_validate_code(size=(120, 30),
chars=init_chars,
img_type="GIF",
mode="RGB",
bg_color=(255, 255, 255),
fg_color=(0, 0, 255),
font_size=18,
font_type="Monaco.ttf",
length=4,
draw_lines=True,
n_line=(1, 2),
draw_points=True,
point_chance=2):
"""
@todo: 生成驗證碼圖片
@param size: 圖片的大小,格式(寬,高),默認為(120, 30)
@param chars: 允許的字元集合,格式字元串
@param img_type: 圖片保存的格式,默認為GIF,可選的為GIF,JPEG,TIFF,PNG
@param mode: 圖片模式,默認為RGB
@param bg_color: 背景顏色,默認為白色
@param fg_color: 前景色,驗證碼字元顏色,默認為藍色#0000FF
@param font_size: 驗證碼字體大小
@param font_type: 驗證碼字體,默認為 ae_AlArabiya.ttf
@param length: 驗證碼字元個數
@param draw_lines: 是否劃干擾線
@param n_lines: 干擾線的條數范圍,格式元組,默認為(1, 2),只有draw_lines為True時有效
@param draw_points: 是否畫干擾點
@param point_chance: 干擾點出現的概率,大小范圍[0, 100]
@return: [0]: PIL Image實例
@return: [1]: 驗證碼圖片中的字元串
"""

width, height = size # 寬高
# 創建圖形
img = Image.new(mode, size, bg_color)
draw = ImageDraw.Draw(img) # 創建畫筆

def get_chars():
"""生成給定長度的字元串,返回列表格式"""
return random.sample(chars, length)

def create_lines():
"""繪制干擾線"""
line_num = random.randint(*n_line) # 干擾線條數

for i in range(line_num):
# 起始點
begin = (random.randint(0, size[0]), random.randint(0, size[1]))
# 結束點
end = (random.randint(0, size[0]), random.randint(0, size[1]))
draw.line([begin, end], fill=(0, 0, 0))

def create_points():
"""繪制干擾點"""
chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100]

for w in range(width):
for h in range(height):
tmp = random.randint(0, 100)
if tmp > 100 - chance:
draw.point((w, h), fill=(0, 0, 0))

def create_strs():
"""繪制驗證碼字元"""
c_chars = get_chars()
strs = ' %s ' % ' '.join(c_chars) # 每個字元前後以空格隔開

# font = ImageFont.truetype(font_type, font_size)
font = ImageFont.load_default().font
font_width, font_height = font.getsize(strs)

draw.text(((width - font_width) / 3, (height - font_height) / 3),
strs, font=font, fill=fg_color)

return ''.join(c_chars)

if draw_lines:
create_lines()
if draw_points:
create_points()
strs = create_strs()

# 圖形扭曲參數
params = [1 - float(random.randint(1, 2)) / 100,
0, 0, 0, 1 - float(random.randint(1, 10)) / 100, float(random.randint(1, 2)) / 500, 0.001, float(random.randint(1, 2)) / 500 ]
img = img.transform(size, Image.PERSPECTIVE, params) # 創建扭曲
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) # 濾鏡,邊界加強(閾值更大)

7. pythonchallenge 去除驗證碼干擾線用什麼演算法好

struct模塊還提供了pack_into() 和 unpack_from()的方法用來解決這樣的問題,也就是對一個已經提前分配好的buffer進行位元組的填充,而不會每次都產生一個新對象對位元組進行存儲。

8. python怎麼批量提交驗證碼

現在的網頁中,為了防止機器人提交表單,圖片驗證碼是很常見的應對手段之一。這里就不詳細介紹了,相信大家都遇到過。
現在就給出用Python的PIL庫實現驗證碼圖片的代碼。代碼中有詳細注釋。
#!/usr/bin/env python
#coding=utf-8
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter
_letter_cases = "abcdefghjkmnpqrstuvwxy" # 小寫字母,去除可能幹擾的i,l,o,z
_upper_cases = _letter_cases.upper() # 大寫字母
_numbers = ''.join(map(str, range(3, 10))) # 數字
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
def create_validate_code(size=(120, 30),
chars=init_chars,
img_type="GIF",
mode="RGB",
bg_color=(255, 255, 255),
fg_color=(0, 0, 255),
font_size=18,
font_type="ae_AlArabiya.ttf",
length=4,
draw_lines=True,
n_line=(1, 2),
draw_points=True,
point_chance = 2):
'''
@todo: 生成驗證碼圖片
@param size: 圖片的大小,格式(寬,高),默認為(120, 30)
@param chars: 允許的字元集合,格式字元串
@param img_type: 圖片保存的格式,默認為GIF,可選的為GIF,JPEG,TIFF,PNG
@param mode: 圖片模式,默認為RGB
@param bg_color: 背景顏色,默認為白色
@param fg_color: 前景色,驗證碼字元顏色,默認為藍色#0000FF
@param font_size: 驗證碼字體大小
@param font_type: 驗證碼字體,默認為 ae_AlArabiya.ttf
@param length: 驗證碼字元個數
@param draw_lines: 是否劃干擾線
@param n_lines: 干擾線的條數范圍,格式元組,默認為(1, 2),只有draw_lines為True時有效
@param draw_points: 是否畫干擾點
@param point_chance: 干擾點出現的概率,大小范圍[0, 100]
@return: [0]: PIL Image實例
@return: [1]: 驗證碼圖片中的字元串
'''
width, height = size # 寬, 高
img = Image.new(mode, size, bg_color) # 創建圖形
draw = ImageDraw.Draw(img) # 創建畫筆
def get_chars():
'''生成給定長度的字元串,返回列表格式'''
return random.sample(chars, length)
def create_lines():
'''繪制干擾線'''
line_num = random.randint(*n_line) # 干擾線條數
for i in range(line_num):
# 起始點
begin = (random.randint(0, size[0]), random.randint(0, size[1]))
#結束點
end = (random.randint(0, size[0]), random.randint(0, size[1]))
draw.line([begin, end], fill=(0, 0, 0))
def create_points():
'''繪制干擾點'''
chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100]

for w in xrange(width):
for h in xrange(height):
tmp = random.randint(0, 100)
if tmp > 100 - chance:
draw.point((w, h), fill=(0, 0, 0))
def create_strs():
'''繪制驗證碼字元'''
c_chars = get_chars()
strs = ' %s ' % ' '.join(c_chars) # 每個字元前後以空格隔開

font = ImageFont.truetype(font_type, font_size)
font_width, font_height = font.getsize(strs)
draw.text(((width - font_width) / 3, (height - font_height) / 3),
strs, font=font, fill=fg_color)

return ''.join(c_chars)
if draw_lines:
create_lines()
if draw_points:
create_points()
strs = create_strs()
# 圖形扭曲參數
params = [1 - float(random.randint(1, 2)) / 100,
0,
0,
0,
1 - float(random.randint(1, 10)) / 100,
float(random.randint(1, 2)) / 500,
0.001,
float(random.randint(1, 2)) / 500
]
img = img.transform(size, Image.PERSPECTIVE, params) # 創建扭曲
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) # 濾鏡,邊界加強(閾值更大)
return img, strs
if __name__ == "__main__":
code_img = create_validate_code()
code_img.save("validate.gif", "GIF")
最後結果返回一個元組,第一個返回值是Image類的實例,第二個參數是圖片中的字元串(比較是否正確的作用)。
最後結果返回一個元組,第一個返回值是Image類的實例,第二個參數是圖片中的字元串(比較是否正確的作用)。
需要提醒的是,如果在生成ImageFont.truetype實例的時候拋出IOError異常,有可能是運行代碼的電腦沒有包含指定的字體,需要下載安裝。
生成的驗證碼圖片效果:

這時候,細心的同學可能要問,如果每次生成驗證碼,都要先保存生成的圖片,再顯示到頁面。這么做讓人太不能接受了。這個時候,我們需要使用python內置的StringIO模塊,它有著類似file對象的行為,但是它操作的是內存文件。於是,我們可以這么寫代碼:
try:
import cStringIO as StringIO
except ImportError:
import StringIO

mstream = StringIO.StringIO()

img = create_validate_code()[0]
img.save(mstream, "GIF")
這樣,我們需要輸出的圖片的時候只要使用「mstream.getvalue()」即可。比如在Django里,我們首先定義這樣的url:
from django.conf.urls.defaults import *

urlpatterns = patterns('example.views',
url(r'^validate/$', 'validate', name='validate'),
)
在views中,我們把正確的字元串保存在session中,這樣當用戶提交表單的時候,就可以和session中的正確字元串進行比較。
from django.shortcuts import HttpResponse

from validate import create_validate_code

def validate(request):
mstream = StringIO.StringIO()

validate_code = create_validate_code()
img = validate_code[0]
img.save(mstream, "GIF")

request.session['validate'] = validate_code[1]

return HttpResponse(mstream.getvalue(), "image/gif")

9. python 驗證碼 閾值有什麼用

看上去不怎麼難,沒有干擾線沒有粘連沒有扭曲.但我還是沒能用pytesser直接將它識別出來,因為當中有噪點和其他背景雜訊的存在.我的工作就是去掉這些討厭的東西
先介紹一下,我們的工具:
1.Pytesser它是基於一個c語言實現名為tesser的識別工具的python封裝.可惜比較笨,只能做最簡單的識別而且不認識漢字
2.Requests它是我們喜歡寫爬蟲的孩子的最愛,提供人性化的介面,代價是失去了一點效率(寫python就別考慮效率啦)
3.BeautifulSoup它和Requests是一對好機油,讓提取文檔中所需的內容變成一件簡單的事情
4.PIL它是今天的主角,PIL是專門用作圖像處理的庫,很好很強大.熟練的人甚至可以用它來P圖
如何寫爬蟲去實現模擬登錄此處不細說,下面說說怎麼解決驗證碼識別
解決思路如下:
1.先用PIL對圖像做一次圖像增強,因為原圖中數字的邊緣和背景中的雜訊並不是太分明,做了增強之後能將兩者分離.如果不分離,可能會在去噪點的時候導致數字中有部分會缺失
im = Image.open("randomimage/randomImage11.jpg")
im = ImageEnhance.Sharpness(im).enhance(3)參數為3是經過實驗之後感覺比較理想的值,太強不好,太弱也不好
2.做完預處理之後,就是去背景雜訊了.背景雜訊指的是背景中各種明暗變換的色塊,肉眼也許不會注意到這個.但是它的存在會給識別帶來影響.我最初的做法是將圖像轉換為只有黑白兩色,這樣自然就將雜訊轉換成了噪點.
效果如圖
但我希望能去掉噪點,成為這樣

最先想到的是種子染色法 ,什麼是種子染色法請參看這個鏈接
為了防止壞鏈,此處做部分轉載
種子染色法英文叫做Flood Fill ,實際上Flood Fill這個名稱更貼切一點,因為這個方法作用在一個圖的結點上時恰似洪水一樣「淹沒」與之相連的其他結點並以相同的方式蔓延出去,這個方法通常用於計算一個圖的極大連通子圖(這里的「圖」是圖論的概念)。設想一個無向圖,我們從這個圖中一個未標號(「標號」可以理解為「染色」)的結點開始,將此結點和從這個結點出發可達的所有結點都賦予相同的標號(染上相同的顏色),那麼我們就得到了這些被標號的結點所組成的一個極大連通子圖,搜索下一個未標號的結點並重復上述過程我們便可以找到所有的極大連通子圖。「染色」的過程可以用DFS或者BFS實現,如果結點數為V,邊數為E,因為我們在Flood Fill過程中「造訪」每個結點兩次,「造訪」每條邊兩次,所以得到所有極大連通子圖的時間復雜度為o(V+E) 。
來自Wikipedia的一個示例:

想像每個白色方塊為圖中的結點,相鄰的方塊(上下左右)有邊相連,那麼這個圖就有三個極大連通子圖,這演示了Flood Fill查找其中一個極大連通子圖的過程。
在這是借要用種子染色法計算每塊的面積,然後把小體積的塊當作噪點去除.
代碼在這

def check(j,i):
try:
if pix[j,i] == 0 and matrix[j][i] != -1:
return True
else:
return False
except:
return False

def juli(r,s):
return abs(r[0]-s[0])+abs(r[1]-s[1])+abs(r[2]-s[2])

for i in range(w):
for j in range(h):
r = [0,0,0]
s = [0,0,0]
if pix[j,i] == 0:
if check(j-1,i):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j-1,i))
print r
print s
print "-"*55
if juli(r,s) <=l:
matrix[j][i] = matrix[j-1][i]
maps[str(matrix[j][i])]+=1
elif check(j-1,i-1):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j-1,i-1))
if juli(r,s) <=l:
matrix[j][i] = matrix[j-1][i-1]
maps[str(matrix[j][i])]+=1
elif check(j,i-1):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j-1,i))
if juli(r,s) <=l:
matrix[j][i] = matrix[j][i-1]
maps[str(matrix[j][i])]+=1
elif check(j+1,i+1):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j+1,i+1))
if juli(r,s) <=l:
matrix[j][i] = matrix[j+1][i+1]
maps[str(matrix[j][i])]+=1
elif check(j,i+1):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j,i+1))
if juli(r,s) <=l:
matrix[j][i] = matrix[j][i+1]
maps[str(matrix[j][i])]+=1
elif check(j-1,i+1):
pr[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j-1,i+1))
if juli(r,s) <=l:
matrix[j][i] = matrix[j-1][i+1]
maps[str(matrix[j][i])]+=1
elif check(j+1,i-1):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j+1,i-1))
if juli(r,s) <=l:
matrix[j][i] = matrix[j+1][i-1]
maps[str(matrix[j][i])]+=1
elif check(j+1,i):
r[0],r[1],r[2] = im2.getpixel((j,i))
s[0],s[1],s[2] = im2.getpixel((j+1,i))
if juli(r,s) <=l:
matrix[j][i] = matrix[j+1][i]
maps[str(matrix[j][i])]+=1
else:
n+=1
maps[str(n)]=1
matrix[j][i] = n
for i in range(w):
for j in range(h):
if matrix[j][i]!=-1 and maps[str(matrix[j][i])]<=2:
im.putpixel((j,i),255)View Code

結果呢,不是很理想因為這個體積參數設小了,噪點沒去干凈,設大了數字部分可能也去了一小塊.最重要的是這里噪點的大小不是很規律,很難找到一個不錯的面積參數.
失敗只是暫時的,經過觀察發現背景雜訊顏色明顯比數字要淺的多.這也意味著它的RGB值要比數字小的多,通過分析RGB值能去掉大部分雜訊,剩下來的噪點可以再通過種子染色法處理.也就是說,分別在兩張圖片(分別是黑白和彩色)上獲取信息,在一張圖片上做處理最後做識別
核心代碼在這
r[0],r[1],r[2] = im2.getpixel((j,i))
if r[0]+r[1]+r[2]>=400 or r[0]>=250 or r[1]>=250 or r[2]>=250 :
im2.putpixel((j,i),(255,255,255)) 至此,本次識別的問題就搞定啦,成功率在50%以上基本滿足介面的需求