前言
滑塊拼圖驗(yàn)證碼的失敗難度在于每次圖片上缺口位置不一樣,需識(shí)別圖片上拼圖的缺口位置,使用python的opencv庫(kù)來(lái)識(shí)別到
環(huán)境準(zhǔn)備
pip 安裝 opencv-python
pip installl opencv-python
opencv(open source computer vision library)是一個(gè)開源的計(jì)算機(jī)視覺庫(kù),提供了很多處理圖片、視頻的方法。
opencv庫(kù)提供了一個(gè)方法(matchtemplate()):從一張較大的圖片中搜索一張較小圖片,計(jì)算出這張大圖上各個(gè)區(qū)域和小圖相似度。
調(diào)用這個(gè)方法后返回一個(gè)二維數(shù)組(numpy庫(kù)中ndarray對(duì)象),從中就能拿到最佳匹配區(qū)域的坐標(biāo)。
這種使用場(chǎng)景就是滑塊驗(yàn)證碼上背景圖片是大圖,滑塊是小圖。
準(zhǔn)備2張圖片
場(chǎng)景示例
先摳出2張圖片,分別為background.png 和 target.png
計(jì)算缺口位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
import cv2 # 作者-上海悠悠 qq交流群:717225969 # blog地址 https://www.cnblogs.com/yoyoketang/ def show(name): '''展示圈出來(lái)的位置''' cv2.imshow( 'show' , name) cv2.waitkey( 0 ) cv2.destroyallwindows() def _tran_canny(image): """消除噪聲""" image = cv2.gaussianblur(image, ( 3 , 3 ), 0 ) return cv2.canny(image, 50 , 150 ) def detect_displacement(img_slider_path, image_background_path): """detect displacement""" # # 參數(shù)0是灰度模式 image = cv2.imread(img_slider_path, 0 ) template = cv2.imread(image_background_path, 0 ) # 尋找最佳匹配 res = cv2.matchtemplate(_tran_canny(image), _tran_canny(template), cv2.tm_ccoeff_normed) # 最小值,最大值,并得到最小值, 最大值的索引 min_val, max_val, min_loc, max_loc = cv2.minmaxloc(res) top_left = max_loc[ 0 ] # 橫坐標(biāo) # 展示圈出來(lái)的區(qū)域 x, y = max_loc # 獲取x,y位置坐標(biāo) w, h = image.shape[:: - 1 ] # 寬高 cv2.rectangle(template, (x, y), (x + w, y + h), ( 7 , 249 , 151 ), 2 ) show(template) return top_left if __name__ = = '__main__' : top_left = detect_displacement( "target.png" , "background.png" ) print (top_left) |
運(yùn)行效果看到黑色圈出來(lái)的地方就說明找到了缺口位置
調(diào)試完成后去掉 show 的這部分代碼
1
2
3
4
5
6
|
# 展示圈出來(lái)的區(qū)域 # x, y = max_loc # 獲取x,y位置坐標(biāo) # w, h = image.shape[::-1] # 寬高 # cv2.rectangle(template, (x, y), (x + w, y + h), (7, 249, 151), 2) # show(template) |
缺口的位置只需得到橫坐標(biāo),距離左側(cè)的位置top_left為184
參考博客:
ps:python opencv破解滑動(dòng)驗(yàn)證碼之獲取缺口位置的示例代碼
破解滑塊驗(yàn)證碼的思路主要有2種:
- 一張完整的背景圖和一張有缺口的圖片的場(chǎng)景,解決思路:兩張圖片同一個(gè)坐標(biāo)位置進(jìn)行像素上的一一對(duì)比,找出不一樣的坐標(biāo)。
- 一張有缺口的圖片和需要驗(yàn)證的小圖,解決思路:1.兩張圖片進(jìn)行二極化以及歸一化,確定小圖在圖片中間的坐標(biāo)。這種辦法我沒有驗(yàn)證通過,可以參考。2.通過opencv獲得缺口位置
- 之后就要使用初中物理知識(shí)了,使用先加速后減速模仿人手動(dòng)拖動(dòng)
- 通過opencv獲得圖片的缺口位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#coding=utf-8 import cv2 import numpy as np from pil import image def get_element_slide_distance(): otemp = 'captcha2.png' oblk = 'captcha1.png' target = cv2.imread(otemp, 0 ) # 讀取進(jìn)行色度圖片,轉(zhuǎn)換為numpy中的數(shù)組類型數(shù)據(jù) template = cv2.imread(oblk, 0 ) width, height = target.shape[:: - 1 ] # 獲取缺口圖數(shù)組的形狀 -->缺口圖的寬和高 temp = 'temp.jpg' # 將處理之后的圖片另存 targ = 'targ.jpg' cv2.imwrite(temp, template) cv2.imwrite(targ, target) target = cv2.imread(targ) # 讀取另存的滑塊圖 target = cv2.cvtcolor(target, cv2.color_bgr2gray) # 進(jìn)行色彩轉(zhuǎn)換 # 去除白色部分 獲取滑塊正常大小 target = target[target. any ( 1 )] target = abs ( 255 - target) # 獲取色差的絕對(duì)值 cv2.imwrite(targ, target) # 保存圖片 target = cv2.imread(targ) # 讀取滑塊 template = cv2.imread(temp) # 讀取背景圖 result = cv2.matchtemplate(target, template, cv2.tm_ccoeff_normed) # 比較兩張圖的重疊區(qū)域 top, left = np.unravel_index(result.argmax(), result.shape) # 獲取圖片的缺口位置 #缺口位置 print ((left, top, left + width, top + height)) # 背景圖中的圖片缺口坐標(biāo)位置 #調(diào)用pil image 做測(cè)試 image = image. open ( "captcha1.png" ) rectangle = (left + 3 , top + 3 , left + width - 3 , top + height - 3 ) #去掉白色塊的影響(上面去掉白色部分的功能并沒有真的起作用) #切割 imagecrop = image.crop(rectangle) #保存切割的缺口 imagecrop.save( "new_image.jpg" ) return left + 3 distance = get_element_slide_distance() # 滑動(dòng)距離誤差校正,滑動(dòng)距離*圖片在網(wǎng)頁(yè)上顯示的縮放比-滑塊相對(duì)的初始位置 distance = distance * ( 280 / 680 ) - 22 |
拖動(dòng)軌跡
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
def generate_tracks1(xcoordinates): element = browser.find_element_by_xpath( "//div[@class='secsdk-captcha-drag-icon sc-jkjlte fsbato']" ) actionchains(browser).click_and_hold(on_element = element).perform() # # actionchains(browser).move_by_offset(xoffset=0, yoffset=y - 445).perform() # # time.sleep(0.15) # print("第二步,拖動(dòng)元素") distance = xcoordinates - 60 # 初速度 v = 0 # 單位時(shí)間為0.2s來(lái)統(tǒng)計(jì)軌跡,軌跡即0.2內(nèi)的位移,越低看起來(lái)越絲滑!! t = 0.08 # 位移/軌跡列表,列表內(nèi)的一個(gè)元素代表0.2s的位移 tracks = [] # 當(dāng)前的位移 current = 0 # 到達(dá)mid值開始減速 mid = distance * 5 / 8 distance + = 10 # 先滑過一點(diǎn),最后再反著滑動(dòng)回來(lái) # a = random.randint(1,3) while current < distance: if current < mid: # 加速度越小,單位時(shí)間的位移越小,模擬的軌跡就越多越詳細(xì) a = random.randint( 100 , 200 ) # 加速運(yùn)動(dòng) else : a = - random.randint( 2 , 10 ) # 減速運(yùn)動(dòng) # 初速度 v0 = v # 0.2秒時(shí)間內(nèi)的位移 s = v0 * t + 0.5 * a * (t * * 2 ) # 當(dāng)前的位置 current + = s # 添加到軌跡列表 tracks.append( round (s)) # 速度已經(jīng)達(dá)到v,該速度作為下次的初速度 v = v0 + a * t if current > distance: break # 反著滑動(dòng)到大概準(zhǔn)確位置 # for i in range(4): # tracks.append(-random.randint(1, 3)) # for i in range(4): # tracks.append(-random.randint(1,3)) random.shuffle(tracks) count = 0 for item in tracks: print (item) count + = item actionchains(browser).move_by_offset(xoffset = item, yoffset = random.randint( - 2 , 2 )).perform() # actionchains(browser).move_to_element_with_offset(to_element=element, xoffset=xcoordinates-18,yoffset=y - 445).perform() # time.sleep(2) # # 釋放鼠標(biāo) print (count) actionchains(browser).release(on_element = element).perform() |
到此這篇關(guān)于python3 使用opencv計(jì)算滑塊拼圖驗(yàn)證碼缺口位置的文章就介紹到這了,更多相關(guān)python滑塊拼圖驗(yàn)證碼內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://www.cnblogs.com/yoyoketang/p/14731542.html