123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- import cv2
- import numpy as np
- import functools
- # 一个帮助缓存化加速的类,引入事实上的全局变量
- class MyValues:
- def __init__(self):
- self.idx = 0
- self.image, self.template = None, None
- def set_val(self, image, template):
- self.idx += 1
- self.image, self.template = image, template
- my_value = MyValues()
- @functools.lru_cache(maxsize=None, typed=False)
- def match_template(w, h, idx):
- image, template = my_value.image, my_value.template
- resized = cv2.resize(template, dsize=(w, h))
- scores = cv2.matchTemplate(image, resized, cv2.TM_CCOEFF_NORMED)
- ind = np.unravel_index(np.argmax(scores, axis=None), scores.shape)
- return ind, scores[ind]
- def match_template_by_scale(scale):
- image, template = my_value.image, my_value.template
- w, h = round(template.shape[1] * scale), round(template.shape[0] * scale)
- ind, score = match_template(w, h, idx=my_value.idx)
- return ind, score, scale
- def search_template(scale=(0.5, 2), search_num=200):
- image, template = my_value.image, my_value.template
- # 局部暴力搜索算法,寻找最优的scale
- tmp = []
- min_scale, max_scale = scale
- max_scale = min(max_scale, image.shape[0] / template.shape[0], image.shape[1] / template.shape[1])
- max_idx = 0
- for i in range(2):
- for scale in np.linspace(min_scale, max_scale, search_num):
- ind, score, scale = match_template_by_scale(scale)
- tmp.append([ind, score, scale])
- # 寻找最佳
- max_idx = 0
- max_score = 0
- for idx, (ind, score, scale) in enumerate(tmp):
- if score > max_score:
- max_idx, max_score = idx, score
- min_scale, max_scale = tmp[max(0, max_idx - 1)][2], tmp[min(len(tmp) - 1, max_idx + 1)][2]
- search_num = 2 * int((max_scale - min_scale) * max(template.shape[1], template.shape[0])) + 1
- return tmp[max_idx]
- def estimate_crop_parameters(original_file=None, template_file=None, ori_img=None, tem_img=None
- , scale=(0.5, 2), search_num=200):
- # 推测攻击后的图片,在原图片中的位置、大小
- if template_file:
- tem_img = cv2.imread(template_file, cv2.IMREAD_GRAYSCALE) # template image
- if original_file:
- ori_img = cv2.imread(original_file, cv2.IMREAD_GRAYSCALE) # image
- if scale[0] == scale[1] == 1:
- # 不缩放
- scale_infer = 1
- scores = cv2.matchTemplate(ori_img, tem_img, cv2.TM_CCOEFF_NORMED)
- ind = np.unravel_index(np.argmax(scores, axis=None), scores.shape)
- ind, score = ind, scores[ind]
- else:
- my_value.set_val(image=ori_img, template=tem_img)
- ind, score, scale_infer = search_template(scale=scale, search_num=search_num)
- w, h = int(tem_img.shape[1] * scale_infer), int(tem_img.shape[0] * scale_infer)
- x1, y1, x2, y2 = ind[1], ind[0], ind[1] + w, ind[0] + h
- return (x1, y1, x2, y2), ori_img.shape, score, scale_infer
- def recover_crop(template_file=None, tem_img=None, output_file_name=None, loc=None, image_o_shape=None):
- if template_file:
- tem_img = cv2.imread(template_file) # template image
- (x1, y1, x2, y2) = loc
- img_recovered = np.zeros((image_o_shape[0], image_o_shape[1], 3))
- img_recovered[y1:y2, x1:x2, :] = cv2.resize(tem_img, dsize=(x2 - x1, y2 - y1))
- if output_file_name:
- cv2.imwrite(output_file_name, img_recovered)
- return img_recovered
|