基于圖像處理的滑塊驗證碼匹配技術

滑塊驗證碼是一種常見的驗證碼形式,通過拖動滑塊與背景圖像中的缺口進行匹配,驗證用戶是否為真人。本文將詳細介紹基于圖像處理的滑塊驗證碼匹配技術,并提供優化代碼以提高滑塊位置偏移量的準確度,尤其是在背景圖滑塊陰影較淺的情況下。

一、背景知識

1.1 圖像處理概述

圖像處理是指對圖像進行分析和操作,以達到增強圖像、提取特征、識別模式等目的。常用的圖像處理技術包括高斯模糊、Canny 邊緣檢測、輪廓提取等。

1.2 滑塊驗證碼的原理

滑塊驗證碼通過用戶拖動滑塊,使滑塊圖像與背景圖像中的缺口對齊,從而驗證用戶的操作。實現滑塊驗證碼匹配的關鍵在于精確檢測背景圖像中缺口的位置。

二、技術實現

2.1 代碼實現

import base64
import os
from datetime import datetime
from typing import Union, Optionalimport cv2
import numpy as npclass SliderCaptchaMatch:def __init__(self,gaussian_blur_kernel_size=(5, 5),gaussian_blur_sigma_x=0,canny_threshold1=200,canny_threshold2=450,save_images=False,output_path=""):"""初始化SlideMatch類:param gaussian_blur_kernel_size: 高斯模糊核大小,默認(5, 5):param gaussian_blur_sigma_x: 高斯模糊SigmaX,默認0:param canny_threshold1: Canny邊緣檢測閾值1,默認200:param canny_threshold2: Canny邊緣檢測閾值2,默認450:param save_images: 是否保存過程圖片,默認False:param output_path: 生成圖片保存路徑,默認當前目錄"""self.GAUSSIAN_BLUR_KERNEL_SIZE = gaussian_blur_kernel_sizeself.GAUSSIAN_BLUR_SIGMA_X = gaussian_blur_sigma_xself.CANNY_THRESHOLD1 = canny_threshold1self.CANNY_THRESHOLD2 = canny_threshold2self.save_images = save_imagesself.output_path = output_pathdef _remove_alpha_channel(self, image):"""移除圖像的alpha通道:param image: 輸入圖像:return: 移除alpha通道后的圖像"""if image.shape[2] == 4:  # 如果圖像有alpha通道alpha_channel = image[:, :, 3]rgb_channels = image[:, :, :3]# 創建一個白色背景white_background = np.ones_like(rgb_channels, dtype=np.uint8) * 255# 使用alpha混合圖像與白色背景alpha_factor = alpha_channel[:, :, np.newaxis] / 255.0image_no_alpha = rgb_channels * alpha_factor + white_background * (1 - alpha_factor)return image_no_alpha.astype(np.uint8)else:return imagedef _get_gaussian_blur_image(self, image):"""對圖像進行高斯模糊處理:param image: 輸入圖像:return: 高斯模糊處理后的圖像"""return cv2.GaussianBlur(image, self.GAUSSIAN_BLUR_KERNEL_SIZE, self.GAUSSIAN_BLUR_SIGMA_X)def _get_canny_image(self, image):"""對圖像進行Canny邊緣檢測:param image: 輸入圖像:return: Canny邊緣檢測后的圖像"""return cv2.Canny(image, self.CANNY_THRESHOLD1, self.CANNY_THRESHOLD2)def _get_contours(self, image):"""獲取圖像的輪廓:param image: 輸入圖像:return: 輪廓列表"""contours, _ = cv2.findContours(image, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)return contoursdef _get_contour_area_threshold(self, image_width, image_height):"""計算輪廓面積閾值:param image_width: 圖像寬度:param image_height: 圖像高度:return: 最小和最大輪廓面積閾值"""contour_area_min = (image_width * 0.15) * (image_height * 0.25) * 0.8contour_area_max = (image_width * 0.15) * (image_height * 0.25) * 1.2return contour_area_min, contour_area_maxdef _get_arc_length_threshold(self, image_width, image_height):"""計算輪廓弧長閾值:param image_width: 圖像寬度:param image_height: 圖像高度:return: 最小和最大弧長閾值"""arc_length_min = ((image_width * 0.15) + (image_height * 0.25)) * 2 * 0.8arc_length_max = ((image_width * 0.15) + (image_height * 0.25)) * 2 * 1.2return arc_length_min, arc_length_maxdef _get_offset_threshold(self, image_width):"""計算偏移量閾值:param image_width: 圖像寬度:return: 最小和最大偏移量閾值"""offset_min = 0.2 * image_widthoffset_max = 0.85 * image_widthreturn offset_min, offset_maxdef _is_image_file(self, file_path: str) -> bool:"""檢查字符串是否是有效的圖像文件路徑"""valid_extensions = ('.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff')return os.path.isfile(file_path) and file_path.lower().endswith(valid_extensions)def _is_base64(self, s: str) -> bool:"""檢查字符串是否是有效的 base64 編碼"""try:if isinstance(s, str):# Strip out data URI scheme if presentif "data:" in s and ";" in s:s = s.split(",")[1]base64.b64decode(s)return Truereturn Falseexcept Exception:return Falsedef _read_image(self, image_source: Union[str, bytes], imread_flag: Optional[int] = None) -> np.ndarray:"""讀取圖像:param image_source: 圖像路徑或base64編碼:param imread_flag: cv2.imread 和 cv2.imdecode 的標志參數 (默認: None):return: 讀取的圖像"""if isinstance(image_source, str):if self._is_image_file(image_source):  # 如果是文件路徑if imread_flag is not None:return cv2.imread(image_source, imread_flag)else:return cv2.imread(image_source)elif self._is_base64(image_source):  # 如果是 base64 編碼# 剝離數據URI方案(如果存在)if "data:" in image_source and ";" in image_source:image_source = image_source.split(",")[1]img_data = base64.b64decode(image_source)img_array = np.frombuffer(img_data, np.uint8)if imread_flag is not None:image = cv2.imdecode(img_array, imread_flag)else:image = cv2.imdecode(img_array, cv2.IMREAD_UNCHANGED)if image is None:raise ValueError("Failed to decode base64 image")return imageelse:raise ValueError("The provided string is neither a valid file path nor a valid base64 string")else:raise ValueError("image_source must be a file path or base64 encoded string")def get_slider_offset(self, background_source: Union[str, bytes], slider_source: Union[str, bytes],out_file_name: str = None) -> int:"""獲取滑塊的偏移量:param background_source: 背景圖像路徑或base64編碼:param slider_source: 滑塊圖像路徑或base64編碼:param out_file_name: 輸出圖片的文件名: 默認為當前時間戳:return: 滑塊的偏移量"""background_image = self._read_image(background_source)slider_image = self._read_image(slider_source, cv2.IMREAD_UNCHANGED)out_file_name = out_file_name if out_file_name else datetime.now().strftime('%Y%m%d%H%M%S.%f')[:-3]if background_image is None:raise ValueError("Failed to read background image")if slider_image is None:raise ValueError("Failed to read slider image")slider_image_no_alpha = self._remove_alpha_channel(slider_image)image_height, image_width, _ = background_image.shapeimage_gaussian_blur = self._get_gaussian_blur_image(background_image)image_canny = self._get_canny_image(image_gaussian_blur)contours = self._get_contours(image_canny)if self.save_images:# 創建輸出目錄if not os.path.exists(self.output_path):os.makedirs(self.output_path)cv2.imwrite(os.path.join(self.output_path, f'{out_file_name}_image_canny.png'), image_canny)cv2.imwrite(os.path.join(self.output_path, f'{out_file_name}_image_gaussian_blur.png'), image_gaussian_blur)contour_area_min, contour_area_max = self._get_contour_area_threshold(image_width, image_height)arc_length_min, arc_length_max = self._get_arc_length_threshold(image_width, image_height)offset_min, offset_max = self._get_offset_threshold(image_width)offset = Nonefor contour in contours:x, y, w, h = cv2.boundingRect(contour)if contour_area_min < cv2.contourArea(contour) < contour_area_max and \arc_length_min < cv2.arcLength(contour, True) < arc_length_max and \offset_min < x < offset_max:cv2.rectangle(background_image, (x, y), (x + w, y + h), (0, 0, 255), 2)offset = x# 匹配滑塊模板在背景中的位置result = cv2.matchTemplate(background_image, slider_image_no_alpha, cv2.TM_CCOEFF_NORMED)_, _, _, max_loc = cv2.minMaxLoc(result)slider_x, slider_y = max_locoffset = slider_xcv2.rectangle(background_image, (slider_x, slider_y),(slider_x + slider_image_no_alpha.shape[1], slider_y + slider_image_no_alpha.shape[0]),(255, 0, 0), 2)if self.save_images:cv2.imwrite(os.path.join(self.output_path, f'{out_file_name}_image_label.png'), background_image)return offset

2.2 代碼說明

  • 圖像預處理:通過高斯模糊和Canny邊緣檢測增強圖像的對比度和亮度,提高滑塊識別率。
  • 多圖像融合:通過多次處理圖像并融合結果,以減小噪聲對檢測結果的影響。
  • 動態調整閾值:根據圖像的直方圖動態調整Canny邊緣檢測的閾值,提高對不同圖像的適應性。
  • 輪廓檢測:通過 _get_contours 函數獲取圖像的輪廓,并根據輪廓面積和弧長進行篩選。
  • 滑塊匹配:通過模板匹配方法 cv2.matchTemplate 匹配滑塊在背景圖中的位置。

2.3 優化策略

  • 對比度和亮度增強:通過提高圖像的對比度和亮度,使得滑塊和背景的區別更加明顯,增強滑塊匹配的準確度。
  • 多圖像融合:融合多張處理后的圖像,減小單張圖像中的噪聲對結果的影響。
  • 動態調整參數:根據圖像內容動態調整Canny邊緣檢測的閾值,使得算法對不同類型的圖像都有較好的適應性。

2.4 安裝依賴

要運行上述代碼,需要安裝以下 Python 庫:

pip install numpy opencv-python slider_captcha_match

2.5 使用方法

在安裝完所需庫后,您可以按照以下步驟使用滑塊驗證碼匹配功能:

  1. 初始化SliderCaptchaMatch類:配置高斯模糊、Canny邊緣檢測等參數。
  2. 讀取背景圖像和滑塊圖像:可以是文件路徑或base64編碼。
  3. 獲取滑塊偏移量:調用get_slider_offset函數,返回滑塊的準確偏移量。
from slider_captcha_match import SliderCaptchaMatchfrom datetime import datetimeimport cv2# 初始化 SliderCaptchaMatch 類slider_captcha_match = SliderCaptchaMatch(save_images=True,output_path="output")# 讀取背景圖像和滑塊圖像background_source = "path_to_background_image.jpg"slider_source = "path_to_slider_image.png"# 獲取滑塊偏移量offset = slider_captcha_match.get_slider_offset(background_source, slider_source)print(f"滑塊偏移量: {offset}")# 輸出結果保存路徑out_file_name = datetime.now().strftime('%Y%m%d%H%M%S.%f')[:-3]print(f"結果圖像保存路徑: output/{out_file_name}_image_label.png")

三、測試與驗證

為了驗證優化后的滑塊驗證碼匹配技術,進行多次測試,比較不同情況下的滑塊偏移量檢測結果,并記錄背景圖、滑塊圖、中間預處理圖和代碼標注的滑塊位置的圖,以及缺口坐標位置偏移量計算。

Response for row 1: offset(手動標注)=155;缺口坐標(代碼計算)=155.0

?

Response for row 2: offset(手動標注)=119;缺口坐標(代碼計算)=118.5


Response for row 2: offset(手動標注)=223;缺口坐標(代碼計算)=224.0

四、總結

本文介紹了基于圖像處理的滑塊驗證碼匹配技術,并通過多種優化策略提高了滑塊位置偏移量的檢測準確度。通過對圖像進行預處理、融合多張圖像、動態調整閾值等方法,可以有效提高滑塊驗證碼在不同背景下的識別率。希望這篇文章能夠對從事圖像處理和驗證碼研究的讀者有所幫助。

參考資料

  1. OpenCV 官方文檔
  2. NumPy 官方文檔
  3. 本Github項目源碼地址

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/41546.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41546.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/41546.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

上海市計算機學會競賽平臺2023年2月月賽丙組平分數字(一)

題目描述 給定 &#x1d45b;n 個整數&#xff1a;&#x1d44e;1,&#x1d44e;2,??,&#x1d44e;&#x1d45b;a1?,a2?,?,an?&#xff0c;請判定能否將它們分成兩個部分&#xff08;不得丟棄任何數字&#xff09;&#xff0c;每部分的數字之和一樣大。 輸入格式 第…

模擬,CF 570C - Replacement

一、題目 1、題目描述 2、輸入輸出 2.1輸入 2.2輸出 3、原題鏈接 570C - Replacement 二、解題報告 1、思路分析 1、長為cnt的連續串的最小操作次數為cnt - 1 2、每次將一個非. 替換為. f要么增加1要么增加2 只有前后都是 . 的時候會增加2 同理&#xff0c;當我們將一…

STM32外擴SRAM及用法

一.概述 一般單片機有片內的RAM&#xff0c;但都不多&#xff0c;比如&#xff1a;STM32F407ZGT6 自帶了 192K 字節的 RAM&#xff0c;對一般應用來說&#xff0c;已經足夠了&#xff0c;不過在一些對內存要求高的場合&#xff0c;比如做華麗效果的 GUI&#xff0c;處理大量數據…

swagger的接口文檔導入到yapi上

一、訪問swagger接口 swagger集成到項目后&#xff0c;通過http:\\ip:port/swagger-ui.html 訪問。 說明&#xff1a;這里的路徑是基于swagger2。如果用swagger3&#xff0c;需要用swagger3的路徑進行訪問。 訪問如圖&#xff1a; 這就是swagger接口首頁。如果想導入到yapi上…

module_param_named 內核啟動時模塊參數實現原理

基于上節內核啟動參數實現原理內容, 其中對early_param的實現流程做了分析, 已基本清晰. 但有不少的參數是在內核模塊中聲明的, 具體賦值流程也值得一探究竟. nomodeset 裝過Linux系統的同學可能多少有看到過nomodeset這個參數, 解決一些顯卡點不亮Linux的問題. 那么這個nomo…

AI繪畫Stable Diffusion 新手入門教程:萬字長文解析Lora模型的使用,快速上手Lora模型!

大家好&#xff0c;我是設計師阿威 今天給大家講解一下AI繪畫Stable Diffusion 中的一個重要模型—Lora模型&#xff0c;如果還有小伙伴沒有SD安裝包的&#xff0c;可以看我往期入門教程2024最新超強AI繪畫Stable Diffusion整合包安裝教程&#xff0c;零基礎入門必備&#xff…

React Hooks --- 分享自己開發中常用的自定義的Hooks (1)

為什么要使用自定義 Hooks 自定義 Hooks 是 React 中一種復用邏輯的機制&#xff0c;通過它們可以抽離組件中的邏輯&#xff0c;使代碼更加簡潔、易讀、易維護。它們可以在多個組件中復用相同的邏輯&#xff0c;減少重復代碼。 1、useThrottle 代碼 import React,{ useRef,…

三葉青圖像識別研究簡概

三葉青圖像識別研究總概 文章目錄 前言一、整體目錄介紹二、前期安排三、構建圖像分類數據集四、模型訓練準備五、遷移學習模型六、在測試集上評估模型精度七、可解釋性分析、顯著性分析八、圖像分類部署九、樹莓派部署十、相關補充總結 前言 本系列文章為近期所做項目研究而作…

工作助手VB開發筆記(2)

今天繼續講功能 2.功能 2.9開機自啟 設置程序隨windows系統啟動&#xff0c;其實就是就是將程序加載到注冊表 Public Sub StartRunRegHKLM()REM HKEY_LOCAL_MACHINE \ SOFTWARE \ WOW6432Node \ Microsoft \ Windows \ CurrentVersion \ RunDim strName As String Applicat…

教師商調函流程詳解

作為一名教師&#xff0c;您是否曾面臨過工作調動的困惑&#xff1f;當您決定邁向新的教育環境&#xff0c;是否清楚整個商調函流程的每一個細節&#xff1f;今天&#xff0c;就讓我們一起來探討這一過程&#xff0c;確保您能夠順利地完成工作調動。 首先需要確定新調入的學校已…

裁員風波中的項目經理,如何自洽?

最近都在擔心企業裁員&#xff0c;那么項目經理會不會也有被優化的風險呢&#xff1f; 答案是&#xff0c;一定會&#xff01; 今天從3個方面給大家闡述一下項目經理崗位的發展現狀以及未來的趨勢 01 項目經理被優化的可能性大嗎&#xff1f; 02 哪一類項目經理會被最先裁員…

CSDN導入本地md文件圖片不能正常回顯問題

標題 搭建圖像倉庫獲取圖片URL 路徑替換 因為服務器讀取不到本地圖片&#xff0c;故不能正常回顯&#xff0c;因此想要正常回顯圖片&#xff0c;我們首先要做的就是搭建一個可以存放圖片的服務器&#xff0c;像你可以選擇購買一個云服務器、FastDFS圖片服務器、Minio多云對象存…

信息收集-arping

信息收集-arping 簡介 arping 是一個用于發送 ARP 請求和接收 ARP 回復的工具。它通常用于檢查網絡中的 IP 地址是否被使用&#xff0c;或發現網絡中的重復 IP 地址。arping 工具類似于 ping 命令&#xff0c;但它使用的是 ARP 協議而不是 ICMP 協議。在 Kali Linux 中&#…

娛樂圈驚爆已婚男星劉端端深夜幽會

【娛樂圈驚爆&#xff01;已婚男星劉端端深夜幽會&#xff0c;竟是《慶余年》二皇子“戲外風云”】在這個信息爆炸的時代&#xff0c;娛樂圈的每一次風吹草動都能瞬間點燃公眾的熱情。今日&#xff0c;知名娛樂博主劉大錘的一則預告如同投入湖中的巨石&#xff0c;激起了層層漣…

紙電混合階段,如何在線上實現紙電會檔案的協同管理?

隨著國家政策的出臺和引導&#xff0c;電子會計檔案的管理越來越規范&#xff0c;電子會計檔案建設成為打通財務數字化最后一公里的重要一環。但是&#xff0c;當前很多企業的財務管理仍處于電子檔案和紙質檔案并行的階段&#xff0c;如何能將其建立合理清晰關聯&#xff0c;統…

《數字圖像處理-OpenCV/Python》第17章:圖像的特征描述

《數字圖像處理-OpenCV/Python》第17章&#xff1a;圖像的特征描述 本書京東 優惠購書鏈接 https://item.jd.com/14098452.html 本書CSDN 獨家連載專欄 https://blog.csdn.net/youcans/category_12418787.html 第17章&#xff1a;圖像的特征描述 特征檢測與匹配是計算機視覺的…

javascript v8編譯器的使用記錄

我的機器是MacOS Mx系列。 一、v8源碼下載構建 1.1 下載并更新depot_tools git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git export PATH/path/to/depot_tools:$PATH 失敗的話可能是網絡問題&#xff0c;可以試一下是否能ping通&#xff0c;連…

【代碼隨想錄_Day25】452. 用最少數量的箭引爆氣球 435. 無重疊區間 763. 劃分字母區間

Day25 OK&#xff0c;今日份的打卡&#xff01;第二十五天 以下是今日份的總結用最少數量的箭引爆氣球無重疊區間劃分字母區間 以下是今日份的總結 用最少數量的箭引爆氣球無重疊區間劃分字母區間 今天的題目難度不低&#xff0c;而且非常的有意思&#xff0c;盡量還是寫一些…

imx6ull/linux應用編程學習(11)CAN應用編程基礎

關于裸機的can通信&#xff0c;會在其他文章發&#xff0c;這里主要講講linux上的can通信。 與I2C,SPI等同步通訊方式不同&#xff0c;CAN通訊是異步通訊&#xff0c;也就是沒有時鐘信號線來保持信號接收同步&#xff0c;也就是所說的半雙工&#xff0c;無法同時發送與接收&…

python項目常見使用的傳參調試方法

簡介 你是否經常遇到下載的github開源知名項目&#xff0c;不知如何調試&#xff1f;只知道按說明的命令行運行&#xff1f;遇到異常或想改造也無從下手&#xff1f;這篇文檔章將指導你如何入手調試別人的大型開源項目。 常見項目使用說明及代碼如何調試 常見情況一 使用說…