#!/usr/bin/env/ python # -*- coding: utf-8 -*- """ @Time : 2023/2/12 11:20 @Author : 余半盏 @File : rotate_captcha.py @Software: PyCharm """ import cv2 import math import numpy as np from loguru import logger import time from utils.tool import cost_time def circle_point_px(img, accuracy_angle, r=None): rows, cols, _ = img.shape assert 360 % accuracy_angle == 0 x0, y0 = r0, _ = (rows // 2, cols // 2) if r: r0 = r angles = np.arange(0, 360, accuracy_angle) cos_angles = np.cos(np.deg2rad(angles)) sin_angles = np.sin(np.deg2rad(angles)) x = x0 + r0 * cos_angles y = y0 + r0 * sin_angles x = np.round(x).astype(int) y = np.round(y).astype(int) circle_px_list = img[x, y] return circle_px_list def rotate(image, angle, center=None, scale=1.0): # 1 (h, w) = image.shape[:2] # 2 if center is None: # 3 center = (w // 2, h // 2) # 4 M = cv2.getRotationMatrix2D(center, angle, scale) # 5 rotated = cv2.warpAffine(image, M, (w, h)) # 6 return rotated def HSVDistance(c1, c2): """ 计算两个颜色的 HSV(Hue, Saturation, Value)空间中的距离 :param c1: :param c2: :return: """ y1 = 0.299 * c1[0] + 0.587 * c1[1] + 0.114 * c1[2] u1 = -0.14713 * c1[0] - 0.28886 * c1[1] + 0.436 * c1[2] v1 = 0.615 * c1[0] - 0.51498 * c1[1] - 0.10001 * c1[2] y2 = 0.299 * c2[0] + 0.587 * c2[1] + 0.114 * c2[2] u2 = -0.14713 * c2[0] - 0.28886 * c2[1] + 0.436 * c2[2] v2 = 0.615 * c2[0] - 0.51498 * c2[1] - 0.10001 * c2[2] rlt = math.sqrt((y1 - y2) * (y1 - y2) + (u1 - u2) * (u1 - u2) + (v1 - v2) * (v1 - v2)) return rlt def crop_to_square(image): height, width = image.shape[:2] size = min(height, width) start_y = (height - size) // 2 start_x = (width - size) // 2 cropped = image[start_y:start_y+size, start_x:start_x+size] return cropped @cost_time def single_discern(inner_image_brg:bytes, outer_image_brg:bytes): inner_image = cv2.cvtColor(inner_image_brg, cv2.COLOR_BGR2HSV) # 颜色转换 outer_image = cv2.cvtColor(outer_image_brg, cv2.COLOR_BGR2HSV) outer_image = crop_to_square(outer_image) all_deviation = [] for result in range(0, 360): inner = rotate(inner_image, -result) # 顺时针 outer = rotate(outer_image, 0) inner_circle_point_px = circle_point_px(inner, 1, 95) outer_circle_point_px = circle_point_px(outer, 1, 105) total_deviation = 0 for i in range(len(inner_circle_point_px)): in_px = inner_circle_point_px[i] out_px = outer_circle_point_px[i] deviation = HSVDistance(in_px, out_px) total_deviation += deviation all_deviation.append(total_deviation) result = all_deviation.index(min(all_deviation)) return result def export_single_discern(fg_path, bg_path): """ 对于下载的图片转为content处理 :param fg_path: :param bg_path: :return: """ if isinstance(fg_path, str): with open(fg_path, "rb") as f: inner_image_brg = f.read() with open(bg_path, "rb") as f: outer_image_brg = f.read() else: inner_image_brg = fg_path outer_image_brg = bg_path image = np.asarray(bytearray(inner_image_brg), dtype="uint8") inner_image_brg = cv2.imdecode(image, cv2.IMREAD_COLOR) image = np.asarray(bytearray(outer_image_brg), dtype="uint8") outer_image_brg = cv2.imdecode(image, cv2.IMREAD_COLOR) result = single_discern(inner_image_brg, outer_image_brg) return result if __name__ == '__main__': export_single_discern('./tmp/fg_2.png', './tmp/bg_2.png') # 310