简介
Cropman是Github上一个开源的项目,基于opencv2,提供对图片的识别和裁剪的Python接口,项目地址.
项目主页给出了简单的使用方法,通过命令行接收需要处理的图片、裁剪的尺寸、需要保存的图片名,cropper.py为主文件。源程序首先识别图片检测图片中的人脸坐标,如果没有识别到人脸则返回原图片的中心点,如果检测到人脸,则根据返回的人脸坐标值(上左下右4个值)计算中心点,得到中心点后根据已提供的需要裁剪的尺寸计算实际的裁剪尺寸(以上一步得到中心点为中心点,给出的宽高为宽高,同时校验有效宽高),返回相对于原图的裁剪坐标。
hack
稍作修改如下:
def crop(self, img, target_width, target_height):
original_height, original_width = img.shape[:2]
faces = self.detector.detect_faces(img)
if len(faces) == 0: # 未识别到人脸
#print 'No face'
return None, None, None, None
else: # 识别到人脸
top, left, bottom, right = self._bounding_rect(faces)
#print 'Get face:', top, left, bottom, right
return top, left, bottom, right
后续的程序中直接调用此方法来获取人脸识别后的坐标,因为人脸识别现阶段也没有100%有效的实现,此程序也只是对系统中图片处理中不足的一个补充,并不能完全依赖,需要结合实际的业务需求实现逻辑:
....
@classmethod
def crop(cls, size, scale, localname):
original_width, original_height = size
if scale == '4:3':
sx, sy, sx_max, sy_max = 4, 3, 640, 480
else:
sx, sy, sx_max, sy_max = 16, 9, 640, 360
cropper = Cropper()
try:
localname = cls.convert_img_to_jpg(localname)
input_image = cv2.imread(localname)
except IOError:
input_image = None
if input_image is None:
return None
top, left, bottom, right = cropper.crop(input_image, original_width, original_height)
if top:
for i in range(1000):
suit_x, suit_y = i * sx, i * sy
if suit_x > original_width or suit_y > original_height:
suit_x, suit_y = suit_x - 4, suit_y - 3
break
bottom -= top/2
x1 = int((original_width - suit_x)/2.0)
y1 = int((bottom - suit_y)/2.0) if bottom > suit_y else 0
x2 = original_width - x1
y2 = (bottom - y1) if bottom > suit_y else suit_y
input_image = input_image[y1:y2, x1:x2]
new_localname = RandomName.randomname()
try:
cv2.imwrite(new_localname, input_image)
return new_localname
except IOError:
return None
else:
for i in range(1000):
suit_x, suit_y = i * sx, i * sy
if suit_x > original_width or suit_y > original_height:
suit_x, suit_y = suit_x - 4, suit_y - 3
break
x1 = int((original_width - suit_x)/2.0) if original_width > suit_x else 0
y1 = 0
x2 = original_width - x1 if original_width > suit_x else suit_x
y2 = suit_y
input_image = input_image[y1:y2, x1:x2]
new_localname = RandomName.randomname()
try:
cv2.imwrite(new_localname, input_image)
return new_localname
except IOError:
return None