دور زدن کپچا با شبکه عصبی پیچشی در پایتون — راهنمای گام به گام

۱۶۸۸ بازدید
آخرین به‌روزرسانی: ۲۱ تیر ۱۴۰۲
زمان مطالعه: ۱۱ دقیقه
دور زدن کپچا با شبکه عصبی پیچشی در پایتون — راهنمای گام به گام

مکانیزم «کپچا» (CAPTCHA) که مخفف اصطلاح «مکانیزم کاملا خودکار شده و عمومی تورینگ جهت تمایز قائل شدن میان انسان و کامپیوتر» (Completely Automated Public Turing to tell Computers and Humans Apart) است، یک مکانیزم امنیتی به شمار می‌آید که در بسترهای آنلاین و برای تشخیص انسان یا ربات بودن متقاضی سرویس اینترنتی به‌کار می‌رود.

در غالب جریان‌های امنیتی که برای تضمین امنیت کاربران و اطلاعات آن‌ها در سطح وب پدید می‌آیند، جریانی در جهت مخالف و با هدف پیدا کردن حفره‌های امنیتی در آن‌ها شکل می‌گیرند. مکانیزم کپچا نیز از این قاعده مستثنی نیست. در طی چند سال اخیر روش‌های مختلفی برای دور زدن کپچا و دور زدن مکانیزم‌های امنیتی آن طراحی شده است. البته غالب تلاش‌ها برای دور زدن کپچا با هدف افزایش امنیت این مکانیزم امنیتی انجام می‌شود.

دور زدن کپچا

هدف اصلی مکانیزم‌های امنیتی CAPTCHA «حل کننده کپچا» (CAPTCHA Solver)، جلوگیری از دسترسی غیر مجاز به اطلاعات توسط بات‌ها و دیگر نرم‌افزار‌های خودکار «خزنده» (Crawler) اطلاعات است. حل کننده کپچا که به آن «استخراج‌گر متن کپچا» (CAPTCHA Text Extractor) نیز گفته می‌شود، فرایندی جهت استخراج متن از تصاویر کپچا است.

بسیاری از تکنیک‌های حل‌ کننده کپچا، از روش‌های «بازشناسی کاراکترهای نوری» (Optical Character Recognition) و ابزارهایی نظیر Tesseract در «زبان برنامه‌نویسی پایتون» (Python Programming Language) جهت استخراج متن از تصاویر کپچا استفاده می‌کنند.

دور زدن کپچا

با این حال، برای درک بهتر مفاهیم «بینایی کامپیوتر» (Computer Vision) و چگونگی استفاده از این روش‌ها برای استخراج متن از تصاویر کپچا، به خوانندگان و مخاطبان این مطلب توصیه می‌شود که «ابزارهای سفارشی شده» (Custom Tools) خود را جهت چنین کاری پیاده‌سازی نمایند. چنین رویه‌ای، نه تنها درک و فهم خوانندگان و مخاطبان را از روش‌های بینایی ماشین و چگونگی استخراج اطلاعات از تصاویر بالاتر می‌برد، بلکه سبب می‌شود تا آن‌ها بتوانند با کسب دانش در این زمینه، دقت مکانیزم‌های موجود را نیز ارتقاء دهند. در این مطلب، برای استخراج متن از تصاویر و دور زدن کپچا، از کتابخانه‌های Keras و openCV در زبان برنامه‌نویسی پایتون استفاده شده است.

ساختن مدل یادگیری برای دور زدن کپچا

جهت تشخیص متن‌های موجود در تصاویر کپچا، از مدل‌های «شبکه عصبی پیچشی» (Convolutional Neural Network) استفاده خواهد شد. مدل شبکه عصبی پیچشی روی تصاویر مربوط به حروف موجود در تصاویر کپچا آموزش خواهید دید. برای ساختن مدل یادگیری لازم برای دور زدن کپچا، لازم است تا ابتدا هر کدام از حروف موجود در تصاویر جداسازی شوند و برای آموزش شبکه عصبی پیچشی، مورد پردازش قرار بگیرند.

پس از آموزش شبکه عصبی پیچشی روی تصاویر مربوط به حروف موجود در تصاویر، مدل قادر خواهد بود تا «تصاویر کپچای دیده نشده» (Unseen CAPTCHA Images) را به عنوان ورودی دریافت کند و متن‌های موجود در آن‌ها را تشخیص دهد.

دور زدن کپچا
نمونه‌ای از تصاویر آموزشی جهت آموزش شبکه عصبی پیچشی (تشخیص متن در تصاویر کپچا)

همانطور که پیش از این نیز اشاره شد، برای استخراج متن از تصاویر و دور زدن کپچا، از کتابخانه‌های Keras و openCV در زبان برنامه‌نویسی پایتون استفاده خواهد شد.

آماده‌سازی داده‌های آموزشی

اولین قدم برای پیاده‌سازی مدل شبکه عصبی پیچشی، آماده‌سازی داده‌های لازم برای آموزش مدل یادگیری است. برای چنین کاری، هر کدام از تصاویر موجود در مجموعه داده آموزشی، به ترتیب وارد سیستم می‌شوند. سپس، حروف موجود در تصاویر جداسازی و به عنوان یک فایل تصویری جدید ذخیره می‌شوند. همانطور که در تصویر بالا نیز قابل مشاهده است، ساختار مجموعه داده آموزشی و تست به این گونه است که نام انتخاب شده برای هر کدام از تصاویر، نمایش دهنده حروف موجود در تصویر است.

بنابراین، در مرحله اول از پیاده‌سازی شبکه عصبی پیچشی جهت دور زدن کپچا و هک کردن آن، تمامی «وابستگی‌های برنامه‌نویسی» (Programming Dependencies) بارگیری و تصاویر توسط کتابخانه openCV در محیط برنامه‌نویسی پایتون خوانده خواهند شد.

1import pandas as pd
2import numpy as np
3import cv2
4import glob
5import imutils
6from imutils import paths
7import os
8import os.path
9
10captcha_image = '11114.png'
11# Load the image and convert it to grayscale
12image = cv2.imread(captcha_image)
13gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
14 
15# grab the base filename as the text
16filename = os.path.basename(captcha_image)
17captcha_text = os.path.splitext(filename)[0]

در هنگام بررسی تصاویر موجود در مجموعه آموزشی، مشاهده شده است که بعضا حروف موجود در تصاویر کپچا، به «مرز» (Border) تصویر بسیار نزدیک هستند. چنین نقیصه‌ای ممکن است فرایند تشخیص حرف‌های موجود در تصاویر را با اختلال مواجه کند. برای رفع چنین نقیصه‌ای در تصاویر کپچا، از فرایند «لایه‌گذاری» (Padding) استفاده می‌شود تا دو پیکسل به حاشیه تصاویر اضافه شود.

در مرحله بعد، از روش‌های «آستانه‌گذاری» (Thresholding) استفاده می‌شود تا میان پیکسل‌های حروف و پیکسل‌های «پس‌زمینه» (Background) تمایز ایجاد شود و از این طریق، پیکسل‌های پس‌زمینه از پیکسل‌های حروف جدا شوند. در این مطلب، از روش آستانه‌گذاری THRESH_BINARY_INV استفاده شده است؛ با این حال، کاربران می‌توانند از هر روش آستانه‌گذاری دلخواهی برای جداسازی پیکسل‌های پس‌زمینه از پیکسل‌های حروف استفاده کنند.

1# Adding some extra padding around the image
2gray = cv2.copyMakeBorder(gray, 8, 8, 8, 8, cv2.BORDER_REPLICATE)
3
4# applying threshold
5thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV, cv2.THRESH_OTSU)[1]

برای جدا کردن هر کدام از حروف موجود در تصویر، از روش‌های پیدا کردن «کانتور» (Contour) استفاده می‌شود. با توجه به اینکه پس‌زمینه تصاویر سفید است و کنتراست بسیار بالایی با حروف موجود در تصویر دارد، روش‌های شناسایی کانتور با دقت بالایی خواهند توانست تا حروف موجود در تصاویر را جدا کنند. برای چنین کاری، از تابع cv2.findcontours در کتابخانه openCV استفاده شده است.

پس از شناسایی کانتورِ حروف موجود در تصاویر، مختصات پیکسلی مستطیل ایجاد شده در اطراف تصویر حروف (کانتور) استخراج می‌شوند. در برخی از تصاویر کپچا، حروف ممکن است بسیار به یکدیگر نزدیک باشند و یا حتی با یکدیگر هم‌پوشانی داشته باشند. برای مقابله با چنین نقیصه‌ای در سیستم پیاده‌سازی شده، ابتدا کانتور‌های «عریض» (Wide) ایجاد شده در تصاویر کپچا شناسایی می‌شوند. سپس، کانتورهای عریض به دو نیمه تقسیم و مختصات پیکسلی مربوط به دو نیمه کانتور، در یک لیست خالی ذخیره می‌شوند.

1# creating empty list for holding the coordinates of the letters
2letter_image_regions = []
3 
4# finding the contours
5contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
6for contour in contours:
7  # Get the rectangle that contains the contour
8  (x, y, w, h) = cv2.boundingRect(contour)
9        
10  # checking if any counter is too wide
11  # if countour is too wide then there could be two letters joined together or are very close to each other
12  if w / h > 1.25:
13    # Split it in half into two letter regions
14    half_width = int(w / 2)
15    letter_image_regions.append((x, y, half_width, h))
16    letter_image_regions.append((x + half_width, y, half_width, h))
17  else:  
18    letter_image_regions.append((x, y, w, h))

در این مرحله، تصاویر استخراج شده از حروف باید به وسیله نام صحیح‌شان ذخیره شوند. به عنوان نمونه، تصاویر مربوط به حرف (2) باید به شکل $$2.PNG$$ ذخیره شود. همانطور که پیش از این نیز اشاره شد، نام انتخاب شده برای هر کدام از تصاویر، نمایش دهنده حروف موجود در تصویر است. به عبارت دیگر، برای ذخیره تصاویر حروف توسط نام صحیح‌شان، لازم است تا هر کدام از حروف شناسایی شده در تصویر را به وسیله حرفِ متناظر با آن در نامِ فایلِ تصویر ذخیره کنیم.

برای تطابق دادن تصاویر حروف با نام صحیح حروف، لازم است تا تصاویر حروف بر اساس مختصات پیکسلی آن‌ها در محور X مرتب‌سازی و نام صحیح حروف، از چپ به راست و از روی نام فایل تصویر استخراج شوند. سپس، تصویر حروف از تصویر اصلی استخراج و از طریق فرایند «لایه‌گذاری» (Padding)، دو پیکسل به حاشیه تصاویر اضافه می‌شود.

1letter_image_regions = sorted(letter_image_regions, key=lambda x: x[0])
2
3# Save each letter as a single image
4for letter_bounding_box, letter_text in zip(letter_image_regions, captcha_text):
5  # Grab the coordinates of the letter in the image
6  x, y, w, h = letter_bounding_box
7
8  # Extract the letter from the original image with a 2-pixel margin around the edge
9  letter_image = gray[y - 2:y + h + 2, x - 2:x + w + 2]

در مرحله بعد، پارامتر save_path با مکان فیزیکی مشخص شده برای ذخیره‌سازی تصاویر حروف، مقداردهی می‌شود. سپس، تصاویر حروف استخراج شده در پوشه‌‎های جداگانه و براساس نام حروف ذخیره خواهند شد. از قطعه کد زیر، برای استخراج حروف از تمامی تصاویر کپچا در یک پوشه خاص، استفاده می‌شود.

1SOLVED_CAPTCHA_FOLDER = "solved-captchas"
2OUTPUT_FOLDER = "extracted_letters"
3
4
5# Get the path of all the solved captcha images
6solved_captchas = glob.glob(os.path.join(SOLVED_CAPTCHA_FOLDER, "*"))
7counts = {}
8
9# loop over the image paths
10for (i, captcha) in enumerate(solved_captchas):
11    print("processing image {}/{}".format(i + 1, len(solved_captchas)))
12
13    
14    # grab the base filename as the text
15    filename = os.path.basename(captcha)
16    captcha_text = os.path.splitext(filename)[0]
17
18    # Load the image and convert it to grayscale
19    image = cv2.imread(captcha)
20    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
21    
22    # Add some extra padding around the image
23    gray = cv2.copyMakeBorder(gray, 8, 8, 8, 8, cv2.BORDER_REPLICATE)
24
25    # applying threshold
26    thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV, cv2.THRESH_OTSU)[1]
27
28     # finding the contours
29    contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
30
31    # creating empty list for holding the coordinates of the letters
32    letter_image_regions = []
33
34    # Now we will loop through each of the contours and extract the letter
35    for contour in contours:
36        # Get the rectangle that contains the contour
37        (x, y, w, h) = cv2.boundingRect(contour)
38        
39        # checking if any counter is too wide
40        # if countour is too wide then there could be two letters joined together or are very close to each other
41        if w / h > 1.25:
42            # Split it in half into two letter regions
43            half_width = int(w / 2)
44            letter_image_regions.append((x, y, half_width, h))
45            letter_image_regions.append((x + half_width, y, half_width, h))
46        else:
47            
48            letter_image_regions.append((x, y, w, h))
49            
50
51    
52    # Sort the detected letter images based on the x coordinate to make sure
53    # we get them from left-to-right so that we match the right image with the right letter
54    letter_image_regions = sorted(letter_image_regions, key=lambda x: x[0])
55    
56    # Save each letter as a single image
57    for letter_bounding_box, letter_text in zip(letter_image_regions, captcha_text):
58        # Grab the coordinates of the letter in the image
59        x, y, w, h = letter_bounding_box
60
61        # Extract the letter from the original image with a 2-pixel margin around the edge
62        letter_image = gray[y - 2:y + h + 2, x - 2:x + w + 2]
63
64
65        # Get the folder to save the image in
66        save_path = os.path.join(OUTPUT_FOLDER, letter_text)
67
68        # creating different output folder for storing different letters
69        if not os.path.exists(save_path):
70            os.makedirs(save_path)
71
72        # write the letter image to a file
73        count = counts.get(letter_text, 1)
74        p = os.path.join(save_path, "{}.png".format(str(count)))
75        cv2.imwrite(p, letter_image)
76
77        # increment the count
78        counts[letter_text] = count + 1

تا این مرحله، تصاویر آموزشی لازم برای آموزش مدل یادگیری (تصاویر حروف موجود در کپچا) استخراج و ذخیره شده‌اند. در ادامه لازم است تا تصاویر آموزشی استخراج شده «پیش پردازش» (Preprocess) شوند تا برای آموزش مدل شبکه عصبی پیچشی آماده شوند. برای چنین کاری، ابتدا تصاویر استخراج شده در محیط برنامه‌نویسی پایتون وارد و به تصاویر «سطح خاکستری» (Grayscale) تبدیل می‌شوند. از آنجایی که تصاویر استخراج شده ابعاد یکسانی ندارند، ابعاد این تصاویر باید توسط فرایندهای پیش پردازشی، به ابعاد دلخواه کاربر (X و Y دلخواه) تغییر کنند (Resize).

نکته مهم در مورد پیاده‌سازی شبکه‌های عصبی پیچشی با استفاده از کتابخانه Keras این است که داده‌های ورودی توابع این کتابخانه باید سه‌بعدی باشند. از آنجایی که تصاویر سطح خاکستری حروف در کپچا، داده‌های دو‌بعدی هستند، با استفاده از تابع (expand_dims) در کتابخانه numpy، یک بعد به ابعاد تصاویر سطح خاکستری حروف اضافه می‌شود. آرایه مرتبط با داده‌های تصاویر حروف در یک «لیست» (List) خالی به نام data و «برچسب» (Label) داده‌ها (که مترادف با نام تصاویرِ حروف است) در لیستی به نام labels ذخیره می‌شوند.

1letter_folder = 'extracted_letters'
2
3#creating empty lists for storing image data and labels
4data = []
5labels = []
6for image in paths.list_images(letter_folder):
7    img = cv2.imread(image)
8    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
9    img = cv2.resize(img, (30,30))
10    
11    # adding a 3rd dimension to the image
12    img = np.expand_dims(img, axis = 2)
13    
14    #grabing the name of the letter based on the folder it is present in
15    label = image.split(os.path.sep)[-2]
16    
17    # appending to the empty lists
18    data.append(img)
19    labels.append(label)
20
21#converting data and labels to np array
22data = np.array(data, dtype = "float")
23labels = np.array(labels)

برای بهینه کردن فرایند آموزش مدل یادگیری شبکه عصبی پیچشی، مقادیر پیکسلی تصاویر حروف به مقادیری بین صفر و یک نگاشت می‌شوند. در مرحله بعد، تمامی تصاویر موجود در مجموعه داده، به دو دسته «تصاویر آموزشی» (Training Images) و تصاویر «تست» (Test) یا «صحت‌سنجی» (Validation) تقسیم‌بندی می‌شوند. در ادامه، «متغیر‌های هدف» (Target Variables) یا همان برچسب‌های داده‌ها، توسط تابع LabelBinarizer در کتابخانه SciKit-Learn کدبندی خواهند شد.

1#scaling the values of  data between 0 and 1
2data = data/255.0
3
4# Split the training data into separate train and test sets
5from sklearn.model_selection import train_test_split
6(train_x, val_x, train_y, val_y) = train_test_split(data, labels, test_size=0.2, random_state=0)
7
8#one hot encoding
9from sklearn.preprocessing import LabelBinarizer
10lb = LabelBinarizer().fit(train_y)
11train_y = lb.transform(train_y)
12val_y = lb.transform(val_y)

ساختن و آموزش مدل شبکه عصبی پیچشی برای دور زدن کپچا

تا این مرحله، تمامی پیش‌نیازهای لازم برای ساختن یک مدل شبکه عصبی پیچشی آماده شده‌اند. از مدل شبکه عصبی پیچشی برای استخراج متن از تصاویر و دور زدن کپچا استفاده می‌شود.

در این مرحله، با استفاده از توابع موجود در کتابخانه Keras جهت تولید «مدل‌های ترتیبی» (Sequential Models)، یک مدل شبکه عصبی پیچشی ساخته خواهد شد.

1from keras.models import Sequential
2from keras.layers.convolutional import Conv2D, MaxPooling2D
3from keras.layers.core import Flatten, Dense, Dropout
4from keras.callbacks import EarlyStopping
5
6#building model
7model = Sequential()
8model.add(Conv2D(20, (5, 5), padding="same", input_shape=(30, 30, 1), activation="relu"))
9model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
10model.add(Conv2D(50, (5, 5), padding="same", activation="relu"))
11model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
12model.add(Flatten())
13model.add(Dense(128, activation="relu"))
14model.add(Dropout(0.3))
15model.add(Dense(9, activation="softmax"))
16
17model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])

در مرحله بعد، فرایند مدل‌سازی شبکه عصبی پیاده‌سازی شده با استفاده از داده‌های آموزشی آغاز می‌شود. در این مطلب، برای جلوگیری از «بیش‌برازش» (Overfitting) مدل شبکه عصبی پیچشی، از روش «توقف زودهنگام» (Early Stopping) استفاده می‌شود.

1# using early stoping for avoiding overfitting
2estop = EarlyStopping(patience=10, mode='min', min_delta=0.001, monitor='val_loss')
3
4model.fit(train_x, train_y, validation_data=(val_x, val_y), batch_size=32, epochs=50, verbose=1, callbacks = [estop])
دور زدن کپچا
نتایج حاصل از آموزش و صحت‌سنجی مدل شبکه عصبی در استخراج متن و تشخیص حروف موجود در تصاویر کپچا

پس از اینکه آموزش مدل شبکه عصبی پیچشی به پایان رسید، عملکرد سیستم در تشخیص حروف در تصاویر کپچای دیده نشده تست می‌شود. پیش از اینکه قادر باشیم تا حروف موجود در داده‌های تست را تشخیص دهیم، لازم است تا همانند فرایند آماده‌سازی داده‌های آموزشی، ابتدا هر کدام از حروف موجود در تصاویر کپچا استخراج شوند.

1# Load the image and convert it to grayscale
2image = cv2.imread('unsolved-captchas.png')
3gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
4    
5# Add some extra padding around the image
6gray = cv2.copyMakeBorder(gray, 8, 8, 8, 8, cv2.BORDER_REPLICATE)
7
8# threshold the image
9thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV, cv2.THRESH_OTSU)[1]
10
11# find the contours
12contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
13
14
15    
16letter_image_regions = []
17
18# Now we can loop through each of the contours and extract the letter
19
20for contour in contours:
21    # Get the rectangle that contains the contour
22    (x, y, w, h) = cv2.boundingRect(contour)
23    
24    # checking if any counter is too wide
25    # if countour is too wide then there could be two letters joined together or are very close to each other
26    if w / h > 1.25:
27        # Split it in half into two letter regions
28        half_width = int(w / 2)
29        letter_image_regions.append((x, y, half_width, h))
30        letter_image_regions.append((x + half_width, y, half_width, h))
31    else:
32        letter_image_regions.append((x, y, w, h))
33            
34
35# Sort the detected letter images based on the x coordinate to make sure
36# we get them from left-to-right so that we match the right image with the right letter  
37
38letter_image_regions = sorted(letter_image_regions, key=lambda x: x[0])
39
40# Create an output image and a list to hold our predicted letters
41output = cv2.merge([gray] * 3)
42predictions = []
43    
44# Creating an empty list for storing predicted letters
45predictions = []
46    
47# Save out each letter as a single image
48for letter_bounding_box in letter_image_regions:
49    # Grab the coordinates of the letter in the image
50    x, y, w, h = letter_bounding_box
51
52    # Extract the letter from the original image with a 2-pixel margin around the edge
53    letter_image = gray[y - 2:y + h + 2, x - 2:x + w + 2]
54
55    letter_image = cv2.resize(letter_image, (30,30))
56        
57    # Turn the single image into a 4d list of images
58    letter_image = np.expand_dims(letter_image, axis=2)
59    letter_image = np.expand_dims(letter_image, axis=0)
60
61    # making prediction
62    pred = model.predict(letter_image)
63        
64    # Convert the one-hot-encoded prediction back to a normal letter
65    letter = lb.inverse_transform(pred)[0]
66    predictions.append(letter)
67
68
69    # draw the prediction on the output image
70    cv2.rectangle(output, (x - 2, y - 2), (x + w + 4, y + h + 4), (0, 255, 0), 1)
71    cv2.putText(output, letter, (x - 5, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.55, (0, 255, 0), 2)
72
73# Print the captcha's text
74captcha_text = "".join(predictions)
75print("CAPTCHA text is: {}".format(captcha_text))
76
77# Show the annotated image
78cv2.imshow('output',output)
79cv2.waitKey(0)
دور زدن کپچا
نمونه‌ای از عملکرد مدل شبکه‌عصبی پیچشی پیاده‌سازی شده در تشخیص حروف موجود در تصاویر کپچا

جمع‌بندی

روش ارائه شده برای دور زدن کپچا در این مطلب، برای نوع خاصی از تصاویر کپچا بسیار عالی عمل می‌کند. با این حال، انواع مختلفی از کپچا با درجه پیچیدگی متفاوت وجود دارند و مدل شبکه عصبی ارائه شده در این مطلب، در تمامی این حالات، عملکرد خوبی از خود نشان نخواهد داد.

هدف این مطلب، آموزش پیاده‌سازی یک سیستم مبتنی بر یادگیری برای دور زدن کپچا و آشنا کردن خوانندگان و مخاطبان این مطلب با فرایندهای اساسی و لازم برای پیاده‌سازی یک سیستم بینایی کامپیوتر ساده و شخصی شده برای استخراج متن از تصاویر و دور زدن کپچا است.

اگر نوشته بالا برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

^^

بر اساس رای ۱۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
Medium
۴ دیدگاه برای «دور زدن کپچا با شبکه عصبی پیچشی در پایتون — راهنمای گام به گام»

کد رو کپی کردم بدون اینکه خطا داشته باشه هیج نتیجه ایی هم نداره . من ادرس فایل تصویر کپچا و پوشه ی solv و output رو ست کردم فقط. اما کار نمیکنه

سلام شما تونستی بااین کد کپچا حل کنی ممنون میشم بهم بگید

سلام
ممنون بابت اطلاعات مفید
اگر بخوایم اصلا به کپچا برنخوریم چطور راهی هست؟

سلام
وقت شما بخیر
شما میتونید رباتی رو برای رد کردن کپچای فرم بنویسین؟

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *