In this tutorial, we will learn how to select a bounding box or a rectangular region of interest (ROI) in an image in OpenCV. In the past, we had to write our own bounding box selector by handling mouse events. However, now we have the option of using a function selectROI that is natively part of OpenCV.
I am always amazed by the weird choices made in the OpenCV library. You would think that selectROI would be part of highgui which has functions for displaying images, drawing on images etc. However, selectROI is part of the tracking API! As you will notice later in the post, the choices made while writing selectROI are odd. But, before we criticize, we gotta be thankful that someone produced something useful even though it is not perfect.
Let’s dive in and see the usage of selectROI
How to select a region of interest in OpenCV
As selectROI is part of the tracking API, you must have OpenCV 3.0 ( or above ) installed with opencv_contrib.
Let’s start with a sample code. It allows you to select a rectangle in an image, crop the rectangular region and finally display the cropped image.
We will modify the highlighted line to try different options.
C++
#include <opencv2/opencv.hpp>
// selectROI is part of tracking API
#include <opencv2/tracking.hpp>
using namespace std;
using namespace cv;
int main (int argc, char **arv)
{
// Read image
Mat im = imread("image.jpg");
// Select ROI
Rect2d r = selectROI(im);
// Crop image
Mat imCrop = im(r);
// Display Cropped Image
imshow("Image", imCrop);
waitKey(0);
return 0;
}
The same code can be written in Python as
Python
import cv2
import numpy as np
if __name__ == '__main__' :
# Read image
im = cv2.imread("image.jpg")
# Select ROI
r = cv2.selectROI(im)
# Crop image
imCrop = im[int(r[1]):int(r[1]+r[3]), int(r[0]):int(r[0]+r[2])]
# Display cropped image
cv2.imshow("Image", imCrop)
cv2.waitKey(0)
Drag Rectangle From Top Left to Bottom Right
If you are like me, you would prefer to drag a rectangle from the top left corner to the bottom right corner instead of dragging it from the center. We can easily fix that by replacing the highlighted line with the following line.
C++
bool fromCenter = false;
Rect2d r = selectROI(im, fromCenter);
Python
fromCenter = False
r = cv2.selectROI(im, fromCenter)
How to Specify The Window Name?
Won’t it be nice if you could use an existing window instead of ROI selector’s window? Well, here you go.
C++
bool fromCenter = false;
Rect2d r = selectROI("Image", im, fromCenter);
Python
fromCenter = False
r = cv2.selectROI("Image", im, fromCenter)
Don’t want to show crosshair?
Suppose you do not like the crosshair and want to see the rectangle without it. You can modify the code not to show the crosshair.
C++
bool showCrosshair = false;
bool fromCenter = false;
Rect2d r = selectROI("Image", im, fromCenter, showCrosshair);
Python
showCrosshair = False
fromCenter = False
r = cv2.selectROI("Image", im, fromCenter, showCrosshair)
How to Select Multiple Regions of Interest (ROI) of an Image?
The function selectROI also allows you to select multiple regions of interest, but there appear to be two bugs.
Bug Alert 1: As per the instructions, you can drag a rectangle and then press ENTER and drag another rectangle. However, there appears to be a bug in the implementation in OpenCV 3.2. You have to hit ENTER twice after the first rectangle. For all subsequent rectangles, you should hit ENTER once.
C++
// Specify a vector of rectangles (ROI)
vector<Rect2d> rects;
bool fromCenter = false;
// The selected rectangles are in
selectROI("Image", im, rects, fromCenter);
Bug Alert 2: I could not get the python version to work without documentation. The following code runs, but the variable rects is not populated. The function also does not return anything. If you find a fix, please let me know in the comments below.
Python
# Note this code does not work.
# Specify a vector of rectangles (ROI)
rects = []
fromCenter = false
# Select multiple rectangles
selectROI("Image", im, rects, fromCenter)
Hi,
I have to detect objects with diferent orientations. Therefore, I need to annotate them with rotated bounding boxes and orientation of objects are important. Could you please add a feature to the current code which I can put rotated bounding boxes and ground truth shows e.g. centerx,centery,width,height,angle. Angle shows the orientation of objects (-180-180).
Maybe using scroll wheel of mouse to rotate the bounding box until if fits object will be a good way to do so, but I could not implement it and I do not know whether this is the best way to annotate rotated objects with rotated bounding boxes.
You can try calculating it from a guideline that points to the
You can try using a guideline in the annotation to estimate the angle of rotation. I had similar requirements before, so I put my old code together into a nice python class. Take a look:
https://github.com/Morpheus3000/polyROISelector
Just that it uses OpenCV3 now, since I updated to it. Should be what you want, except my model returns the rotation value from 0 to 360, but conversion into your interval should be trivial. 🙂
Thanks a lot. I will try your tool. It is for rotated bounding boxes and not polygons, isn’t it?
It doesn’t allow for dragging out a rotated bounding box, but it does give you the polygon you selected (along with other stuff too). So you can fit a min area bounding box (using opencv built-in functions) with that polygon to get the rotated bounding box.
Hello,
I am having a lot of trouble getting the function selectROI. I used CMake to build OpenCV from source with opencv_contrib. Once the dll’s were created(built using Visual Studio) I moved(from the .binRelease folder) them all into the site-packages folder in my Anaconda directory. “import cv2” works but selectROI is still not registering.
Any help would be appreciated.
Mukesh.
Hi Mukesh,
That is very odd because it works on our windows installation.
Satya
Hello,
Is your problem solved? I seem to have encountered the same problem with you, there is an error: “selectROI” is still not registering, can help me solve it?
Thank you
Hello,
Unfortunately I was not able to solve the problem.
Please let me know if you figure something out.
Thanks.
Mukesh.
I have the same problem, did you find the solution ?
dlls are for building cpp projects. You need Python binary (.pyd) for building python code. Please check my reply to senbo above. If you configure using CMake properly you don’t have to manually copy relevant files.
your download link doesn’t work. it is corrupted apparently. The only thing it does each time is asking to subscribe.
Fix it
Hi Paya,
All the code for this article is in the article itself. For access to code in other articles you need to subscribe. You will receive a welcome email with link.
Satya
this is a code i share on GitHub
https://github.com/amin-git/OpenCV_Select_Non_Rect_ROI
you can select non rectangular ROI from a video
hope useful and improve by help of other!
https://uploads.disquscdn.com/images/3580cc42c7ed718ee083601098da6ffd413aa2171d0e2e8a73c7f0f2a47c3712.png
Hello,Can you tell me your the code‘s running environment? For example: windows‘s version, Visual Studio’s version and debug or release,I tried to win7 and win10 can not run, there is an error: “selectROI” is still not registering,can you help me? thank you
We compiled OpenCV 3.2.0 with contrib modules on Windows 10 using Visual Studio 2017 in release mode. It should work with VS 2015 too. I was using VS 2015 earlier.
When you build “INSTALL” in CMakeTargets using Visual Studio, it will copy either one or both of these files within Lib/site-packages to your Python’s directory.
1. for Python 3 – cv2.cp36-win_amd64.pyd (name may vary depending upon Python3 version and 32-bit/64-bit)
2. for Python 2 – cv2.pyd
in my case these files were generated and copied at Anaconda2Libsite-packages and Anaconda3Libsite-packages
Which cv2 library is generated is dependent on which Python and NumPy was detected by CMake.
If you can give your opencv
3.2 ,its good.(like a link)
I have the same problem, I am using OpenCV 3.2 c++
Hello, I have installed OpenCV 3.0 with opencv_contrib (Ubuntu) and the error is:
$ g++ `pkg-config –cflags opencv` program.cpp `pkg-config –libs opencv` -o program -lopencv_tracking
$ error: ‘selectROI’ was not declared in this scope
Rect2d r = selectROI(“Image”, im, fromCenter, showCrosshair);
Can you help me? thank you
Hi Tomás,
selectROI function was introduced in OpenCV 3.1. As you can see in documentation that this function is available in OpenCV 3.1 – http://docs.opencv.org/3.1.0/d9/df8/group__tracking.html but not in OpenCV 3.0 – http://docs.opencv.org/3.0.0/d9/df8/group__tracking.html
You should install OpenCV 3.1 or 3.2 to use this feature.
Hi Vaibhaw!
Thank you very much, it was very useful.
I get the “AttributeError” when trying to use “selectROI” from Python (3.5), so I end up using an old-style approach by providing its implementation manually.
>>> import cv2
>>> cv2.__version__
‘3.2.0-dev’
>>> cv2.selectROI
Traceback (most recent call last):
File “”, line 1, in
AttributeError: module ‘cv2’ has no attribute ‘selectROI’
Hi,
Can any one pls share the code for Multi-target tracking in real time surveillance video
Hi Satya, Have you figured out how to do multiple ROI in python yet? I am stumped on making this work in python. I tried np arrays pre-created for rectangle dimensions as well but got an error..
Thanks!
Allie
any progress on what you are trying to achieve ?
cause i have stumbled into similar knida problem and unable to resolve it ….
Hello,
Thank you Mr. Satya Mallick, this is very useful tutorial, I have some corrections
selectROI function was declared as the following in opencv3.2.0
C++ @ highgui.hpp
————————————————————————————————————————————–
/** @overload
*/
CV_EXPORTS_W Rect selectROI(InputArray img, bool showCrosshair = true, bool fromCenter = false);
————————————————————————————————————————————–
Python @ __init__.py
————————————————————————————————————————————–
def selectROI(windowName, img, showCrosshair=None, fromCenter=None): # real signature unknown; restored from __doc__
“”” selectROI(windowName, img[, showCrosshair[, fromCenter]]) -> retval or selectROI(img[, showCrosshair[, fromCenter]]) -> retval “””
pass
————————————————————————————————————————————–
So, may you note that showCrosshair parameter comes before fromCenter.
for python, multiple selections still buggy in opencv3.2
Hi Satya, thanks for the tut.
If you can edit it because I almost lost a lot of time reinstalling OpenCV with the contrib modules.
The cv2.selectROI is in the highgui module in the newer versions of OpenCV.
Thanks for the feedback. You are right. Will update after testing.
This is ok but how to get RONI?
Hai i have a question in selecting ROI of video how can we do that?
How to convert image into graph?
Hey,
All your tutorials are very informative and teaches minute details in a very elaborate way…
I am trying to capture the tracked face in webcam camera as an image and i am unable to find any relevant material. Can this program be used to select roi from video, manually…Actually I tried programs to display the rectangle tracking the face as a separate window and then crop the roi but in vain…Could you please help me if you have some idea on this topic?
To select multiple ROI’s in Python:
boundingBoxes = cv2.selectROIs(windowName, img[, showCrosshair[, fromCenter]])
Note the “s” at the end of “selectROIs”. The function returns the list of Rects so you do not need to supply one as a parameter.
Can you please share an example saving and using multiple roi from a same image