Skip to content

Commit

Permalink
Merge pull request #29 from Juannie-PP/luyuan
Browse files Browse the repository at this point in the history
新增像素点标准差和范围设置,可调整值去除裁切图片时的噪点
  • Loading branch information
Juannie-PP authored Jan 27, 2024
2 parents 0daad45 + 1d3c573 commit 0d19a78
Showing 1 changed file with 95 additions and 15 deletions.
110 changes: 95 additions & 15 deletions src/tenon/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,47 @@ def set_mask(radius, check_pixel):
return mask


def cut_image(origin_array, radius=None, check_pixel=None):
def cut_image(origin_array, std, cut_value, radius=None, check_pixel=None):
cut_pixel_list = [] # 上, 左, 下, 右
height, width = origin_array.shape[:2]
if not radius:
for rotate_count in range(4):
cut_pixel = 0
rotate_array = np.rot90(origin_array, rotate_count)
for line in rotate_array:
pixel_set = (
set(list(line)) if len(line.shape) == 1 else set(map(tuple, line))
)
if not pixel_set.issubset({0, 255, (0, 0, 0), (255, 255, 255)}):
break
if len(line.shape) == 1:
pixel_set = set(list(line)) - {0, 255}
else:
pixel_set = set(map(tuple, line)) - {(0, 0, 0), (255, 255, 255)}

if not pixel_set:
cut_pixel += 1
continue

if len(line.shape) == 1:
pixels = tuple(
pixel
for pixel in tuple(pixel_set)
if cut_pixel < pixel < 255 - cut_value
)
pixel_std = np.std(pixels)
if pixel_std > std:
break
else:
count = 0
pixels = [[], [], []]
for b, g, r in pixel_set:
if min(b, g, r) > cut_pixel and max(b, g, r) < 255 - cut_value:
pixels[0].append(b)
pixels[1].append(g)
pixels[2].append(r)

bgr_std = tuple(np.std(pixels[i]) for i in range(3))
for pixel_std in bgr_std:
if pixel_std > std:
count += 1
if count == 3:
break
cut_pixel += 1
cut_pixel_list.append(cut_pixel)
cut_pixel_list[2] = height - cut_pixel_list[2]
Expand All @@ -57,11 +85,19 @@ def cut_image(origin_array, radius=None, check_pixel=None):
p_x, p_y = (pos, y) if len(cut_pixel_list) % 2 else (x, pos)
pixel_point = origin_array[p_x][p_y]
pixel_set = (
{pixel_point}
{pixel_point} - {0, 255}
if isinstance(pixel_point, np.uint8)
else set(pixel_point)
else set(tuple(pixel_point)) - {(0, 0, 0), (255, 255, 255)}
)
if not pixel_set.issubset({0, 255}):
if not pixel_set:
pos += i
continue
status = True
for pixel in pixel_set:
if pixel <= cut_value or pixel >= 255 - cut_value:
status = False
break
if status:
break
pos += i
cut_pixel_list.append(pos + i * resize_check_pixel)
Expand Down Expand Up @@ -134,6 +170,8 @@ def rotate_identify(
speed_ratio: float = 1,
grayscale: bool = False,
anticlockwise: bool = False,
standard_deviation: int = 0,
cut_pixel_value: int = 0,
proxies: Optional[dict] = None,
) -> MatchData:
"""
Expand All @@ -143,17 +181,22 @@ def rotate_identify(
:param image_type: 图片类型: 0: 图片base64; 1: 图片url; 2: 图片文件地址
:param grayscale: 是否需要灰度化处理: True: 是; False: 否
:param check_pixel: 进行图片验证的像素宽度
:param anticlockwise: 图片旋转的类型: True: 小圈逆时针; False: 小圈顺时针
:param speed_ratio: 小圈与大圈的转动速率比: 小圈转动360度时/大圈转动的角度
:param grayscale: 是否需要灰度化处理: True: 是; False: 否
:param anticlockwise: 图片旋转的类型: True: 小圈逆时针; False: 小圈顺时针
:param standard_deviation: 计算行/列像素点值的标准差
:param cut_pixel_value: 需要裁切的像素点值; 保留值区间range(cut_pixel_value, 255 - cut_pixel_value)
:param proxies: 代理
:return: namedtuple -> MatchData
"""
inner_image = image_to_cv2(small_circle, image_type, grayscale, proxies)
outer_image = image_to_cv2(big_circle, image_type, grayscale, proxies)

cut_inner_image = cut_image(inner_image)
cut_inner_image = cut_image(inner_image, standard_deviation, cut_pixel_value)
cut_inner_radius = cut_inner_image.shape[0] // 2
cut_outer_image = cut_image(outer_image, cut_inner_radius, check_pixel)
cut_outer_image = cut_image(
outer_image, standard_deviation, cut_pixel_value, cut_inner_radius, check_pixel
)

inner_annulus = mask_image(cut_inner_image, check_pixel)
outer_annulus = mask_image(cut_outer_image, check_pixel)
Expand Down Expand Up @@ -195,9 +238,12 @@ def rotate_identify_and_show_image(
big_circle: str,
image_type: int = 0,
check_pixel: int = 10,
image_show_time: int = 0,
grayscale: bool = False,
anticlockwise: bool = False,
standard_deviation: int = 0,
cut_pixel_value: int = 0,
image_show_time: int = 0,
image_add: bool = False,
proxies: Optional[dict] = None,
):
"""
Expand All @@ -208,16 +254,21 @@ def rotate_identify_and_show_image(
:param grayscale: 是否需要灰度化处理: True: 是; False: 否
:param check_pixel: 进行图片验证的像素宽度
:param anticlockwise: 图片旋转的类型: True: 小圈逆时针; False: 小圈顺时针
:param standard_deviation: 计算行/列像素点值的标准差, 标准差设置过大会造成图片被完全裁切
:param cut_pixel_value: 需要裁切的像素点值; 保留值区间range(cut_pixel_value, 255 - cut_pixel_value)
:param image_show_time: 调试下显式图片时间, 默认常态显式
:param image_add: 旋转后的内外圈图片叠加显示
:param proxies: 代理
:return: namedtuple -> MatchData
"""
inner_image = image_to_cv2(small_circle, image_type, grayscale, proxies)
outer_image = image_to_cv2(big_circle, image_type, grayscale, proxies)

cut_inner_image = cut_image(inner_image)
cut_inner_image = cut_image(inner_image, standard_deviation, cut_pixel_value)
cut_inner_radius = cut_inner_image.shape[0] // 2
cut_outer_image = cut_image(outer_image, cut_inner_radius, check_pixel)
cut_outer_image = cut_image(
outer_image, standard_deviation, cut_pixel_value, cut_inner_radius, check_pixel
)

cv2.imshow("cut_inner_image", cut_inner_image)
cv2.imshow("cut_outer_image", cut_outer_image)
Expand All @@ -237,4 +288,33 @@ def rotate_identify_and_show_image(
cv2.imshow("cut_outer_image", cut_outer_image)
cv2.imshow("outer_image", outer_image)
cv2.imshow("rotated_inner_image", rotated_inner_image)

if image_add:
origin_h, origin_w = inner_image.shape[:2]
mat_rotate = cv2.getRotationMatrix2D(
(origin_h // 2, origin_w // 2), rotate_angle, 1
)
rotated_origin_inner_image = cv2.warpAffine(
inner_image, mat_rotate, inner_image.shape[:2]
)
inner_mask = cv2.circle(
np.zeros(inner_image.shape[:2], dtype=np.uint8),
(origin_h // 2, origin_w // 2),
height // 2,
(255, 255, 255),
-1,
)
outer_mask = set_mask(origin_h // 2, origin_w // 2 - height // 2)

sad = cv2.add(
rotated_origin_inner_image,
np.zeros(outer_image.shape, dtype=np.uint8),
mask=inner_mask,
)
sad2 = cv2.add(
outer_image, np.zeros(outer_image.shape, dtype=np.uint8), mask=outer_mask
)

image_add_view = cv2.add(sad, sad2)
cv2.imshow("image_add", image_add_view)
cv2.waitKey(image_show_time * 1000)

0 comments on commit 0d19a78

Please sign in to comment.