1

Hi I am am working on a small script that would make repetitive picture cropping easier. I wrote a small script that gets the x,y coordinates from the image using mouse event and I am trying to use a code that i have found in the openCV tutorials for cropping an image with a face to certain sizes for a facial database.

import sys, math
import Image
import cv2
import numpy as np
import Tkinter
import tkFileDialog
from Tkinter import Tk
from tkFileDialog import askopenfilename
def Distance(p1,p2):
 dx = p2[0] - p1[0]
 dy = p2[1] - p1[1]
 return math.sqrt(dx*dx+dy*dy)
def ScaleRotateTranslate(image, angle, center = None, new_center = None, scale = None, resample=Image.BICUBIC):
 if (scale is None) and (center is None):
 return image.rotate(angle=angle, resample=resample)
 nx,ny = x,y = center
 sx=sy=1.0
 if new_center:
 (nx,ny) = new_center
 if scale:
 (sx,sy) = (scale, scale)
 cosine = math.cos(angle)
 sine = math.sin(angle)
 a = cosine/sx
 b = sine/sx
 c = x-nx*a-ny*b
 d = -sine/sy
 e = cosine/sy
 f = y-nx*d-ny*e
 return image.transform(image.size, Image.AFFINE, (a,b,c,d,e,f), resample=resample)
def CropFace(image, eye_left=(0,0), eye_right=(0,0), offset_pct=(0.2,0.2), dest_sz = (70,70)):
 # calculate offsets in original image
 offset_h = math.floor(float(offset_pct[0])*dest_sz[0])
 offset_v = math.floor(float(offset_pct[1])*dest_sz[1])
 # get the direction
 eye_direction = (eye_right[0] - eye_left[0], eye_right[1] - eye_left[1])
 # calc rotation angle in radians
 rotation = -math.atan2(float(eye_direction[1]),float(eye_direction[0]))
 # distance between them
 dist = Distance(eye_left, eye_right)
 # calculate the reference eye-width
 reference = dest_sz[0] - 2.0*offset_h
 # scale factor
 scale = float(dist)/float(reference)
 # rotate original around the left eye
 image = ScaleRotateTranslate(image, center=eye_left, angle=rotation)
 # crop the rotated image
 crop_xy = (eye_left[0] - scale*offset_h, eye_left[1] - scale*offset_v)
 crop_size = (dest_sz[0]*scale, dest_sz[1]*scale)
 image = image.crop((int(crop_xy[0]), int(crop_xy[1]), int(crop_xy[0]+crop_size[0]), int(crop_xy[1]+crop_size[1])))
 # resize it
 image = image.resize(dest_sz, Image.ANTIALIAS)
 return image
 # mouse callback function
def getCoord(event,x,y,flags,param):
 global click
 global xs
 global ys
 global xs1
 global ys1
 if event == cv2.EVENT_LBUTTONDOWN:
 print str(x) + " " + str(y)
 with open("coords.txt", "a") as myfile:
 if click == 0:
 xs = x
 ys = y
 #myfile.write(str(x) + " " + str(y) + " ")
 if click == 1:
 xs1 = x
 ys1 = y
 #myfile.write(str(x) + " " + str(y) + "\n")
 print "Press 'Esc' to go to next picture or to exit" 
 click += 1
if __name__ == "__main__":
 global click
 global xs
 global ys
 global xs1
 global ys1
 print "\n"
 print "\n"
 click = 0
 fileList = []
 root = Tkinter.Tk()
 filez = tkFileDialog.askopenfilenames(parent=root,title='Choose a file/files')
 fileList = root.tk.splitlist(filez)
 print root.tk.splitlist(filez)
 lenght = len(fileList)
 print str(lenght)
 for num in range(0,lenght):
 if click == 0:
 print "test"
 image = cv2.imread(str(fileList[num]), cv2.IMREAD_COLOR)
 cv2.namedWindow("Find and Cropp")
 cv2.setMouseCallback("Find and Cropp", getCoord)
 cv2.imshow("Find and Cropp", image)
 if cv2.waitKey(0) & 0xFF == 27:
 cv2.destroyWindow("Find and Cropp")
 if click > 0:
 elx = int(xs)
 #print xs
 ely = int(ys)
 #print ys
 erx = int(xs1)
 #print xs1
 ery = int(ys1)
 #print ys1
 if click == 2: 
 #CropFace(image, eye_left=(115,115), eye_right=(168,120), offset_pct=(0.1,0.1), dest_sz=(200,200)).save("01a.jpg")
 CropFace(image, eye_left=(elx,ely), eye_right=(erx,ery), offset_pct=(0.2,0.2), dest_sz=(200,200)).save("data/" + str(num+1) + ".jpg")
 CropFace(image, eye_left=(elx,ely), eye_right=(erx,ery), offset_pct=(0.3,0.3), dest_sz=(200,200)).save("data/" + str(num+1) + "a.jpg")
 #CropFace(image, eye_left=(115,115), eye_right=(168,120), offset_pct=(0.2,0.2)).save("01d.jpg")
 print "********************" + str(num+1) + ".jpg - saved"
 click = 0
 cv2.destroyWindow("Find and Cropp")

Te error that I am getting is AttributeError: 'numpy.ndarray' object has no atribute 'transform'

The error starts on the line:

CropFace(image, eye_left=(elx,ely), eye_right=(erx,ery), offset_pct=(0.2,0.2), dest_sz=(200,200)).save("data/" + str(num+1) + ".jpg")

and finishesh at line:

return image.transform(image.size, Image.AFFINE, (a,b,c,d,e,f), resample=resample)

But when i run the code just for cropping the face (the coordinates were obtained earlier using a first script and saved to a text file) everything is running fine.

asked Apr 19, 2014 at 21:10
3
  • I don't immediately see the problem, but that's also a bit hard because it's just so much code. If you could narrow down your code to the minimal sample that shows when it works and doesn't work, it would be easier to help, plus you might come across the problem along the way yourself. Commented Apr 19, 2014 at 22:43
  • @Nicolas78: Added some comments... Commented Apr 20, 2014 at 0:37
  • Did you trace your code line by line, seeing the value of every variables and making sure that they have the right value?! Commented Apr 20, 2014 at 11:46

1 Answer 1

2

There is a difference between OpenCV and PIL dealing with images. OpenCV is dealing with images as a NumPy array, but PIL stores it as a PIL.Image object.

A NumPy array object doesn't have a transform function, but a PIL Image object has.

If you don't wish to implement the crop face function yourself, first change the NumPy array into a PIL image, and the change the PIL image into a NumPy array.

Change

CropFace(image, eye_left=(elx,ely), eye_right=(erx,ery), offset_pct=(0.3,0.3), dest_sz=(200,200)).save("data/" + str(num+1) + "a.jpg")

into

CropFace(Image.fromarray(np.uint8(image)), eye_left=(elx,ely), eye_right=(erx,ery), offset_pct=(0.3,0.3), dest_sz=(200,200)).save("data/" + str(num+1) + "a.jpg")
Peter Mortensen
31.3k22 gold badges110 silver badges134 bronze badges
answered Jul 30, 2014 at 2:03
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.