You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.6 KiB
123 lines
3.6 KiB
#!/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
|