bytefish.de

archiving photos: extracting images

I had another 10 minutes for my small archiving project this morning. Turns out I should have listened to my 7th grade1) math teacher: Trigonometry is actually important. And now that I have worked myself through all “Trigonometry for kids” pages google shows up, it turns out I don't need all this for OpenCV.

You basically only need getRotationMatrix2D to get the rotation matrix for the affine transformation and getRectSubPix to crop the rotated image. Thanks a lot to: http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/, it would have taken me a lot more minutes if I didn't see getRectSubPix.

In OpenCV this translates to (rest of code doesn't change):

// [...]
	for (int i = 0; i < contours.size(); i++) {
		// first calculate the area to remove small areas
		double area = contourArea(contours[i]);
		// you probably have to adjust the size of the area
		// as it depends on the size of the rectangle
		if (area > 10000) {
			// get the bounding box of this contour
			RotatedRect rect = minAreaRect(contours[i]);
			// matrices we'll use
			Mat M, rotated, cropped;
 
			// get angle and size from the bounding box
			float angle = rect.angle;
			Size rect_size = rect.size;
 
			// thanks to http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/
			if (rect.angle < -45.) {
				angle += 90.0;
				swap(rect_size.width, rect_size.height);
			}
 
			// http://opencv.willowgarage.com/documentation/cpp/geometric_image_transformations.html#cv-getrotationmatrix2d
			M = getRotationMatrix2D(rect.center, angle, 1.0);
			// http://opencv.willowgarage.com/documentation/cpp/geometric_image_transformations.html#cv-warpaffine
			warpAffine(src, rotated, M, src.size(), INTER_CUBIC);
			// yes yes, just a little scroll above getRotationMatrix2D:
			// http://opencv.willowgarage.com/documentation/cpp/geometric_image_transformations.html#cv-getrectsubpix
			getRectSubPix(rotated, rect_size, rect.center, cropped);
 
			imshow("cropped", cropped);
			waitKey(0);
			// write to file
			//std::stringstream ssfilename;
			//ssfilename << filename << i << ".jpg";
			//imwrite(ssfilename.str(), cropped);
		}
	}
[...]

and you end up with your extracted pictures:

So next thing is to put all this into a GUI! Forgot to mention I hacked a small Python Tkinter application to manually crop and rotate images: files/python/cropper.py.

1) Or was it 6th grade? I can't even remember.

Discussion

Johanna, 2011/10/10 02:41

OpenCV makes our life easier…lol

Philipp Wagner, 2011/10/10 10:58

Yep, but in the end it's sufficient to apply some smoothing (for example gaussian) and use adaptive thresholding. That yields much better results, than finding edges with a canny filter.

Christian, 2011/10/13 09:42

Automatically archiving pictures sounds interesting. There is something more u can do to add certain images to groups of interests with clustering algorthims :) maybe u will save time without to create folders and adding pictures to them ;)

Philipp Wagner, 2011/10/18 16:32

Hey! I wish it was that easy to cluster images. The only thing, that quickly comes to my mind is to cluster by color intensities (and applying OpenCVs built in object detection algorithms).

In statistics you usually have some structured data and you try to find the distribution of the process behind it. The only thing that's probably done to the input data is some sort of preprocessing. Throw the outliers away, replace unknown values, normalize, …

But in computer vision you have to extract features from your image first:

  • And what's a meaningful feature of an image?
  • Does this feature change if I scale it?
  • What if I rotate the image?
  • What if illumination changes?

That's the sort of things you have to deal with before applying a clustering algorithm to image data. Too many what if for a small project. :-)

Enter your comment. Wiki syntax is allowed: