Spaces:
Runtime error
Runtime error
import cv2 | |
from numpy import asarray as np_as_array | |
from numpy import all as np_all | |
class CaptchaProcessor: | |
WHITE_RGB = (255, 255, 255) | |
def __init__(self, data: bytes): | |
self.img = cv2.imdecode( | |
np_as_array(bytearray(data), dtype="uint8"), | |
cv2.IMREAD_ANYCOLOR | |
) | |
def threshold(self): | |
self.img = cv2.threshold(self.img, 0, 255, cv2.THRESH_OTSU)[1] | |
def convert_color_space(self, target_space: int): | |
self.img = cv2.cvtColor(self.img, target_space) | |
def get_background_color(self) -> tuple: | |
return tuple(self.img[0, 0]) | |
def resize(self, x: int, y: int): | |
self.img = cv2.resize(self.img, (x, y)) | |
def save(self, name: str): | |
cv2.imwrite(name, self.img) | |
def get_letters_color(self) -> tuple: | |
colors = [] | |
for y in range(self.img.shape[1]): | |
for x in range(self.img.shape[0]): | |
color = tuple(self.img[x, y]) | |
if color != self.WHITE_RGB: colors.append(color) | |
return max(set(colors), key=colors.count) | |
def replace_color(self, target: tuple, to: tuple): | |
self.img[np_all(self.img == target, axis=-1)] = to | |
def replace_colors(self, exception: tuple, to: tuple): | |
self.img[np_all(self.img != exception, axis=-1)] = to | |
def increase_contrast(self, alpha: float, beta: float): | |
self.img = cv2.convertScaleAbs(self.img, alpha=alpha, beta=beta) | |
def increase_letters_size(self, add_pixels: int): | |
pixels = [] | |
for y in range(self.img.shape[1]): | |
for x in range(self.img.shape[0]): | |
if self.img[x, y] == 0: pixels.append((x, y)) | |
for y, x in pixels: | |
for i in range(1, add_pixels + 1): | |
self.img[y + i, x] = 0 | |
self.img[y - i, x] = 0 | |
self.img[y, x + i] = 0 | |
self.img[y, x - i] = 0 | |
self.img[y + i, x] = 0 | |
self.img[y - i, x] = 0 | |
self.img[y, x + i] = 0 | |
self.img[y, x - i] = 0 | |
# Отдаление символов друг от друга | |
# Может многократно повысить точность, но я так и не придумал правильную реализацию | |
def distance_letters(self, cf: float): | |
pixels = [] | |
for y in range(self.img.shape[1]): | |
for x in range(self.img.shape[0]): | |
if self.img[x, y] == 0: pixels.append((x, y)) | |
for y, x in pixels: | |
self.img[y, x] = 255 | |
center = self.img.shape[1] / 2 | |
z = self.img.shape[1] / x | |
if z >= 2: self.img[y, x - int((900 // x) * cf)] = 0 | |
else: self.img[y, x + int((900 // x) * cf)] = 0 | |
def slice_letters(self): | |
contours, hierarchy = cv2.findContours(self.img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) | |
letter_image_regions = [] | |
letters = [] | |
for idx, contour in enumerate(contours): | |
if hierarchy[0][idx][3] != 0: continue | |
(x, y, w, h) = cv2.boundingRect(contour) | |
if w / h > 1.5: | |
half_width = int(w / 2) | |
letter_image_regions.append((idx, x, y, half_width, h)) | |
letter_image_regions.append((idx, x + half_width, y, half_width, h)) | |
else: | |
letter_image_regions.append((idx, x, y, w, h)) | |
letter_image_regions = sorted(letter_image_regions, key=lambda z: z[1]) | |
for _, x, y, w, h in letter_image_regions: | |
frame = self.img[y:y + h, x:x + w] | |
if frame.shape[1] > 35: continue | |
frame = cv2.resize(frame, (20, 40)) | |
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) | |
letters.append(frame) | |
return letters | |
def show(self): | |
cv2.imshow("Captcha Processor", self.img) | |
cv2.waitKey(0) | |
def from_file_name(cls, name: str): | |
file = open(name, "rb") | |
processor = cls(file.read()) | |
file.close() | |
return processor |