
Let me tell you an embarrassing story of how I wasted three weeks of research time during graduate school sixyears ago.
It was the end of my second semester of coursework.
I had taken all of my exams early and all my projects for the semester had beensubmitted.
Since my school obligations were essentially nil, I started experimenting with (automatically) identifyingprescription pills in images , something I know a thing or two about (but back then I was just getting started with my research).
At the time, my research goal was to find and identify methods to reliably quantify pills in a rotation invariant manner. Regardless of how the pill was rotated, I wanted the output feature vector to be (approximately) the same (the feature vectors will never be to completely identical in a real-world application due to lighting conditions, camera sensors, floating point errors, etc.).
After the first week I was making fantastic progress.
I was able to extract features from my dataset of pills, index them, and then identify my test set ofpills regardless of how they wereoriented…
…however, there was a problem:
My method was only working with round, circular pills ― I was getting completely nonsensical results for oblong pills.
How could that be?
I racked my brain for the explanation.
Was there a flaw in the logic of my feature extraction algorithm?
Was I not matching the features correctly?
Or was it something else entirely… like a problem with my image preprocessing.
While I might have been ashamed to admit this as a graduate student, the problem was the latter:
I goofed up.It turns out that during the image preprocessing phase, I was rotating my images incorrectly.
Since round pills have are approximately square in their aspect ratio, the rotation bug wasn’t a problem for them. Here you can see a round pill being rotated a full 360 degrees without an issue:

Figure 1:Rotating a circular pill doesn’t reveal any obvious problems.
But for oblong pills, they would be “cut off” in the rotation process, like this:

Figure 2:However, rotating oblong pills using the OpenCV’s standard cv2.getRotationMatrix2D and cv2.warpAffine functions caused me some problems that weren’t immediately obvious.
In essence, I was only quantifying part of the rotated, oblong pills; hence my strange results.
I spent three weeks and part of my Christmas vacation banging my head against the wall trying to diagnose the bug ― only to feel quite embarrassed when I realized it was due to me being negligent with the cv2 . rotate function.
You see, the size of the output image needs to be adjusted , otherwise, the corners of my image would be cut off.
How did I accomplish this and squash the bug for good?
To learn how to rotate images with OpenCV such that the entire image is included and none of the image is cut off, just keep reading.
Looking for the source code to this post?
Jump right to the downloads section. Rotate images (correctly) with OpenCV and pythonIn the remainder of this blog post I’ll discuss common issues that you may run into when rotating images with OpenCV and Python.
Specifically, we’ll be examining the problem of what happens when the corners of an image are “cut off” during the rotation process.
To make sure we all understand this rotation issue with OpenCV and Python I will:
Start with a simple example demonstrating the rotation problem. Provide a rotation function that ensures images are not cut off in the rotation process. Discuss how I resolved my pill identification issue using this method. A simple rotation problem with OpenCVLet’s get this blog post started with an example script.
Open up a new file, name it rotate_simple . py , and insert the following code:
# import the necessary packages import numpyas np import argparse import imutils import cv2 # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="path to the image file") args = vars(ap.parse_args())Lines 2-5start byimporting our required Python packages.
If you don’t already have imutils , my series of OpenCV convenience functions installed, you’ll want to do that now:
$ pipinstallimutilsIf you already have imutils installed, make sure you have upgraded to the latest version:
$ pipinstall --upgradeimutilsFrom there, Lines 8-10 parse our command line arguments. We only need a single switch here, -- image , which is the path to where our image resides on disk.
Let’s move on to actually rotating our image:
# load the image from disk image = cv2.imread(args["image"]) # loop over the rotation angles for anglein np.arange(0, 360, 15): rotated = imutils.rotate(image, angle) cv2.imshow("Rotated (Problematic)", rotated) cv2.waitKey(0) # loop over the rotation angles again, this time ensuring # no part of the image is cut off for anglein np.arange(0, 360, 15): rotated = imutils.rotate_bound(image, angle) cv2.imshow("Rotated (Correct)", rotated) cv2.waitKey(0)Line 14loads the image we want to rotatefrom disk.
We then loop over various angles in the range [0, 360] in 15 degree increments ( Line 17 ).For each of these angles we call imutils . rotate , which rotates our image the specified number of angle degrees about the center of the image. We then display the rotated image to our screen.
Lines 24-27perform an identical process, but this time we call imutils . rotate_bound (I’ll providethe implementation of this function in the next section).
As the name of this method suggests, we are going to ensure the entire image is bound inside the window and none is cut off.
To see this script in action, be sure to download the source code using the “Downloads” section of this blog post, followed by executing the command below:
$ pythonrotate_simple.py --imageimages/saratoga.jpgThe output of using the imutils . rotate function on a non-square image can be seen below:

Figure 3:An example of corners being