I am learning OpenCV and at the moment I am trying to understand the underlying data stored in a KeyPoint so that I can better utilize that data for an application I'm working on.
So far I have been going through these two pages:
http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_feature_detectors.html?highlight=featuredetector#FeatureDetector
http://docs.opencv.org/doc/tutorials/features2d/feature_detection/feature_detection.html
When I follow the tutorial, however, using drawKeypoints(), the points are all the same size and shape, and are drawn with a seemingly arbitrary color.
I guess I could iterate through the attributes for each key point: draw a circle, draw an arrow (for the angle), give it a color based on the response, etc. But I figured there had to be a better way.
Is there a built-in method or other approach similar to drawKeypoints() that will help me more efficiently visualize the KeyPoints of an image?
Yes, there is the method to perform your task. As says in documentation
For each keypoint the circle around keypoint with keypoint size and
orientation will be drawn
If you are using Java, you can simply specify the type of keypoints:
Features2d.drawKeypoints(image1, keypoints1, imageOut2,new Scalar(2,254,255),Features2d.DRAW_RICH_KEYPOINTS);
In C++:
drawKeypoints( img_1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DRAW_RICH_KEYPOINTS );
I had a similair problem and wanted to customize the points that are drawn, decided to share my solution because I wanted to alter the shape of the points drawn.
You can alter the line with cv2.circle with what you want. im is the input image you want the points to be drawn in, keyp are the keypoints you want to draw, col is the line color, th is the thickness of the circle edge.
import cv2
import numpy as np
import matplotlib.pyplot as plt
def drawKeyPts(im,keyp,col,th):
for curKey in keyp:
x=np.int(curKey.pt[0])
y=np.int(curKey.pt[1])
size = np.int(curKey.size)
cv2.circle(im,(x,y),size, col,thickness=th, lineType=8, shift=0)
plt.imshow(im)
return im
imWithCircles = drawKeyPts(origIm.copy(),keypoints,(0,255,0),5)
You can iterate through the vector of keypoints that you detect and draw (for example) a circle on every KeyPoint.pt having radius analogous to KeyPoint.size and color with respect to KeyPoint.response.. This is of course just an example; you could write more complicated drawing functions based on the octave and angle of the KeyPoint (if your detector gives that output)..
Hope this helps.
hello it is my code #Alex
def drawKeyPts(im, keyp, col, th):
draw_shift_bits = 4
draw_multiplier = 1 << 4
LINE_AA = 16
im = cv2.cvtColor(im, cv2.COLOR_GRAY2BGR)
for curKey in keyp:
center = (int(np.round(curKey.pt[0]*draw_multiplier)), int(np.round(curKey.pt[1]*draw_multiplier)))
radius = int(np.round(curKey.size/2*draw_multiplier))
cv2.circle(im, center, radius, col, thickness=th, lineType=LINE_AA, shift=draw_shift_bits)
if(curKey.angle != -1):
srcAngleRad = (curKey.angle * np.pi/180.0)
orient = (int(np.round(np.cos(srcAngleRad)*radius)), int(np.round(np.sin(srcAngleRad)*radius)))
cv2.line(im, center, (center[0]+orient[0], center[1]+orient[1]), col, 1, LINE_AA, draw_shift_bits)
cv2.imshow('name1', im)
cv2.waitKey()
return im
Related
I have this project where I need (on iOS) to detect simple geometric shapes inside an image.
After searching the internet I have concluded that the best tool for this is OpenCV. The thing is that up until two hours ago I had no idea what OpenCV is and I have never even remotely did anything involving image processing. My main experience is JS/HTML,C#,SQL,Objective-C...
Where do I start with this?
I have found this answer that I was able to digest and by reading already other stuff, I understand that OpenCV should return an Array of shapes with the points/corners, is this true? Also how will it represent a circle or a half circle?
Also what about the shape orientation?
Do you know of any Demo iOS project that can demonstrate a similar functionality?
If you have only these regular shapes, there is a simple procedure as follows :
Find Contours in the image ( image should be binary as given in your question)
Approximate each contour using approxPolyDP function.
First, check number of elements in the approximated contours of all the shapes. It is to recognize the shape. For eg, square will have 4, pentagon will have 5. Circles will have more, i don't know, so we find it. ( I got 16 for circle and 9 for half-circle.)
Now assign the color, run the code for your test image, check its number, fill it with corresponding colors.
Below is my example in Python:
import numpy as np
import cv2
img = cv2.imread('shapes.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,1)
contours,h = cv2.findContours(thresh,1,2)
for cnt in contours:
approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True)
print len(approx)
if len(approx)==5:
print "pentagon"
cv2.drawContours(img,[cnt],0,255,-1)
elif len(approx)==3:
print "triangle"
cv2.drawContours(img,[cnt],0,(0,255,0),-1)
elif len(approx)==4:
print "square"
cv2.drawContours(img,[cnt],0,(0,0,255),-1)
elif len(approx) == 9:
print "half-circle"
cv2.drawContours(img,[cnt],0,(255,255,0),-1)
elif len(approx) > 15:
print "circle"
cv2.drawContours(img,[cnt],0,(0,255,255),-1)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Below is the output:
Remember, it works only for regular shapes.
Alternatively to find circles, you can use houghcircles. You can find a tutorial here.
Regarding iOS, OpenCV devs are developing some iOS samples this summer, So visit their site : www.code.opencv.org and contact them.
You can find slides of their tutorial here : http://code.opencv.org/svn/gsoc2012/ios/trunk/doc/CVPR2012_OpenCV4IOS_Tutorial.pdf
The answer depends on the presence of other shapes, level of noise if any and invariance you want to provide for (e.g. rotation, scaling, etc). These requirements will define not only the algorithm but also required pre-procesing stages to extract features.
Template matching that was suggested above works well when shapes aren't rotated or scaled and when there are no similar shapes around; in other words, it finds a best translation in the image where template is located:
double minVal, maxVal;
Point minLoc, maxLoc;
Mat image, template, result; // template is your shape
matchTemplate(image, template, result, CV_TM_CCOEFF_NORMED);
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc); // maxLoc is answer
Geometric hashing is a good method to get invariance in terms of rotation and scaling; this method would require extraction of some contour points.
Generalized Hough transform can take care of invariance, noise and would have minimal pre-processing but it is a bit harder to implement than other methods. OpenCV has such transforms for lines and circles.
In the case when number of shapes is limited calculating moments or counting convex hull vertices may be the easiest solution: openCV structural analysis
You can also use template matching to detect shapes inside an image.
What is the best way to detect the corners of an invoice/receipt/sheet-of-paper in a photo? This is to be used for subsequent perspective correction, before OCR.
My current approach has been:
RGB > Gray > Canny Edge Detection with thresholding > Dilate(1) > Remove small objects(6) > clear boarder objects > pick larges blog based on Convex Area. > [corner detection - Not implemented]
I can't help but think there must be a more robust 'intelligent'/statistical approach to handle this type of segmentation. I don't have a lot of training examples, but I could probably get 100 images together.
Broader context:
I'm using matlab to prototype, and planning to implement the system in OpenCV and Tesserect-OCR. This is the first of a number of image processing problems I need to solve for this specific application. So I'm looking to roll my own solution and re-familiarize myself with image processing algorithms.
Here are some sample image that I'd like the algorithm to handle: If you'd like to take up the challenge the large images are at http://madteckhead.com/tmp
(source: madteckhead.com)
(source: madteckhead.com)
(source: madteckhead.com)
(source: madteckhead.com)
In the best case this gives:
(source: madteckhead.com)
(source: madteckhead.com)
(source: madteckhead.com)
However it fails easily on other cases:
(source: madteckhead.com)
(source: madteckhead.com)
(source: madteckhead.com)
EDIT: Hough Transform Progress
Q: What algorithm would cluster the hough lines to find corners?
Following advice from answers I was able to use the Hough Transform, pick lines, and filter them. My current approach is rather crude. I've made the assumption the invoice will always be less than 15deg out of alignment with the image. I end up with reasonable results for lines if this is the case (see below). But am not entirely sure of a suitable algorithm to cluster the lines (or vote) to extrapolate for the corners. The Hough lines are not continuous. And in the noisy images, there can be parallel lines so some form or distance from line origin metrics are required. Any ideas?
(source: madteckhead.com)
I'm Martin's friend who was working on this earlier this year. This was my first ever coding project, and kinda ended in a bit of a rush, so the code needs some errr...decoding...
I'll give a few tips from what I've seen you doing already, and then sort my code on my day off tomorrow.
First tip, OpenCV and python are awesome, move to them as soon as possible. :D
Instead of removing small objects and or noise, lower the canny restraints, so it accepts more edges, and then find the largest closed contour (in OpenCV use findcontour() with some simple parameters, I think I used CV_RETR_LIST). might still struggle when it's on a white piece of paper, but was definitely providing best results.
For the Houghline2() Transform, try with the CV_HOUGH_STANDARD as opposed to the CV_HOUGH_PROBABILISTIC, it'll give rho and theta values, defining the line in polar coordinates, and then you can group the lines within a certain tolerance to those.
My grouping worked as a look up table, for each line outputted from the hough transform it would give a rho and theta pair. If these values were within, say 5% of a pair of values in the table, they were discarded, if they were outside that 5%, a new entry was added to the table.
You can then do analysis of parallel lines or distance between lines much more easily.
Hope this helps.
Here's what I came up with after a bit of experimentation:
import cv, cv2, numpy as np
import sys
def get_new(old):
new = np.ones(old.shape, np.uint8)
cv2.bitwise_not(new,new)
return new
if __name__ == '__main__':
orig = cv2.imread(sys.argv[1])
# these constants are carefully picked
MORPH = 9
CANNY = 84
HOUGH = 25
img = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
cv2.GaussianBlur(img, (3,3), 0, img)
# this is to recognize white on white
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(MORPH,MORPH))
dilated = cv2.dilate(img, kernel)
edges = cv2.Canny(dilated, 0, CANNY, apertureSize=3)
lines = cv2.HoughLinesP(edges, 1, 3.14/180, HOUGH)
for line in lines[0]:
cv2.line(edges, (line[0], line[1]), (line[2], line[3]),
(255,0,0), 2, 8)
# finding contours
contours, _ = cv2.findContours(edges.copy(), cv.CV_RETR_EXTERNAL,
cv.CV_CHAIN_APPROX_TC89_KCOS)
contours = filter(lambda cont: cv2.arcLength(cont, False) > 100, contours)
contours = filter(lambda cont: cv2.contourArea(cont) > 10000, contours)
# simplify contours down to polygons
rects = []
for cont in contours:
rect = cv2.approxPolyDP(cont, 40, True).copy().reshape(-1, 2)
rects.append(rect)
# that's basically it
cv2.drawContours(orig, rects,-1,(0,255,0),1)
# show only contours
new = get_new(img)
cv2.drawContours(new, rects,-1,(0,255,0),1)
cv2.GaussianBlur(new, (9,9), 0, new)
new = cv2.Canny(new, 0, CANNY, apertureSize=3)
cv2.namedWindow('result', cv2.WINDOW_NORMAL)
cv2.imshow('result', orig)
cv2.waitKey(0)
cv2.imshow('result', dilated)
cv2.waitKey(0)
cv2.imshow('result', edges)
cv2.waitKey(0)
cv2.imshow('result', new)
cv2.waitKey(0)
cv2.destroyAllWindows()
Not perfect, but at least works for all samples:
A student group at my university recently demonstrated an iPhone app (and python OpenCV app) that they'd written to do exactly this. As I remember, the steps were something like this:
Median filter to completely remove the text on the paper (this was handwritten text on white paper with fairly good lighting and may not work with printed text, it worked very well). The reason was that it makes the corner detection much easier.
Hough Transform for lines
Find the peaks in the Hough Transform accumulator space and draw each line across the entire image.
Analyse the lines and remove any that are very close to each other and are at a similar angle (cluster the lines into one). This is necessary because the Hough Transform isn't perfect as it's working in a discrete sample space.
Find pairs of lines that are roughly parallel and that intersect other pairs to see which lines form quads.
This seemed to work fairly well and they were able to take a photo of a piece of paper or book, perform the corner detection and then map the document in the image onto a flat plane in almost realtime (there was a single OpenCV function to perform the mapping). There was no OCR when I saw it working.
Instead of starting from edge detection you could use Corner detection.
Marvin Framework provides an implementation of Moravec algorithm for this purpose. You could find the corners of the papers as a starting point. Below the output of Moravec's algorithm:
Also you can use MSER (Maximally stable extremal regions) over Sobel operator result to find the stable regions of the image. For each region returned by MSER you can apply convex hull and poly approximation to obtain some like this:
But this kind of detection is useful for live detection more than a single picture that not always return the best result.
After edge-detection, use Hough Transform.
Then, put those points in an SVM(supporting vector machine) with their labels, if the examples have smooth lines on them, SVM will not have any difficulty to divide the necessary parts of the example and other parts. My advice on SVM, put a parameter like connectivity and length. That is, if points are connected and long, they are likely to be a line of the receipt. Then, you can eliminate all of the other points.
Here you have #Vanuan 's code using C++:
cv::cvtColor(mat, mat, CV_BGR2GRAY);
cv::GaussianBlur(mat, mat, cv::Size(3,3), 0);
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Point(9,9));
cv::Mat dilated;
cv::dilate(mat, dilated, kernel);
cv::Mat edges;
cv::Canny(dilated, edges, 84, 3);
std::vector<cv::Vec4i> lines;
lines.clear();
cv::HoughLinesP(edges, lines, 1, CV_PI/180, 25);
std::vector<cv::Vec4i>::iterator it = lines.begin();
for(; it!=lines.end(); ++it) {
cv::Vec4i l = *it;
cv::line(edges, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255,0,0), 2, 8);
}
std::vector< std::vector<cv::Point> > contours;
cv::findContours(edges, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_KCOS);
std::vector< std::vector<cv::Point> > contoursCleaned;
for (int i=0; i < contours.size(); i++) {
if (cv::arcLength(contours[i], false) > 100)
contoursCleaned.push_back(contours[i]);
}
std::vector<std::vector<cv::Point> > contoursArea;
for (int i=0; i < contoursCleaned.size(); i++) {
if (cv::contourArea(contoursCleaned[i]) > 10000){
contoursArea.push_back(contoursCleaned[i]);
}
}
std::vector<std::vector<cv::Point> > contoursDraw (contoursCleaned.size());
for (int i=0; i < contoursArea.size(); i++){
cv::approxPolyDP(Mat(contoursArea[i]), contoursDraw[i], 40, true);
}
Mat drawing = Mat::zeros( mat.size(), CV_8UC3 );
cv::drawContours(drawing, contoursDraw, -1, cv::Scalar(0,255,0),1);
Convert to lab space
Use kmeans segment 2 cluster
Then use contours or hough on one of the clusters (intenral)
I need an algorithm written in any language to find an image inside of an image, including at different scales. Does anyone know a starting point to solving a problem like this?
For example:
I have an image of 800x600 and in that image is a yellow ball measuring 180 pixels in circumference. I need to be able to find this image with a search pattern of a yellow ball having a circumference of 15 pixels.
Thanks
Here's an algorithm:
Split the image into RGB and take the blue channel. You will notice that areas that were yellow in the color image are now dark in the blue channel. This is because blue and yellow are complementary colors.
Invert the blue channel
Create a greyscale search pattern with a circle that's the same size as what's in the image (180 pixels in circumference). Make it a white circle on a black background.
Calculate the cross-correlation of the search pattern with the inverted blue channel.
The cross-correlation peak will correspond to the location of the ball.
Here's the algorithm in action:
RGB and R:
G and B:
Inverted B and pattern:
Python + OpenCV code:
import cv
if __name__ == '__main__':
image = cv.LoadImage('ball-b-inv.png')
template = cv.LoadImage('ball-pattern-inv.png')
image_size = cv.GetSize(image)
template_size = cv.GetSize(template)
result_size = [ s[0] - s[1] + 1 for s in zip(image_size, template_size) ]
result = cv.CreateImage(result_size, cv.IPL_DEPTH_32F, 1)
cv.MatchTemplate(image, template, result, cv.CV_TM_CCORR)
min_val, max_val, min_loc, max_loc = cv.MinMaxLoc(result)
print max_loc
Result:
misha#misha-desktop:~/Desktop$ python cross-correlation.py
(72, 28)
This gives you the top-left co-ordinate of the first occurence of the pattern in the image. Add the radius of the circle to both x and y co-ordinates if you want to find the center of the circle.
You should take a look at OpenCV, an open source computer vision library - this would be a good starting point. Specifically check out object detection and the cvMatchTemplate method.
a version of one of previous posts made with opencv 3 and python 3
import cv2
import sys
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(cv2.matchTemplate(cv2.imread(sys.argv[1]),cv2.imread(sys.argv[2]),cv2.TM_CCOEFF_NORMED))
print(max_loc)
save as file.py and run as:
python file.py image pattern
A simple starting point would be the Hough transform, if you want to find circles.
However there is a whole research area arount this subject called object detection and recognition. The state of the art has advanced significantly the past decade.
I'm trying to use OpenCV to "parse" screenshots from the iPhone game Blocked. The screenshots are cropped to look like this:
I suppose for right now I'm just trying to find the coordinates of each of the 4 points that make up each rectangle. I did see the sample file squares.c that comes with OpenCV, but when I run that algorithm on this picture, it comes up with 72 rectangles, including the rectangular areas of whitespace that I obviously don't want to count as one of my rectangles. What is a better way to approach this? I tried doing some Google research, but for all of the search results, there is very little relevant usable information.
The similar issue has already been discussed:
How to recognize rectangles in this image?
As for your data, rectangles you are trying to find are the only black objects. So you can try to do a threshold binarization: black pixels are those ones which have ALL three RGB values less than 40 (I've found it empirically). This simple operation makes your picture look like this:
After that you could apply Hough transform to find lines (discussed in the topic I referred to), or you can do it easier. Compute integral projections of the black pixels to X and Y axes. (The projection to X is a vector of x_i - numbers of black pixels such that it has the first coordinate equal to x_i). So, you get possible x and y values as the peaks of the projections. Then look through all the possible segments restricted by the found x and y (if there are a lot of black pixels between (x_i, y_j) and (x_i, y_k), there probably is a line probably). Finally, compose line segments to rectangles!
Here's a complete Python solution. The main idea is:
Apply pyramid mean shift filtering to help threshold accuracy
Otsu's threshold to get a binary image
Find contours and filter using contour approximation
Here's a visualization of each detected rectangle contour
Results
import cv2
image = cv2.imread('1.png')
blur = cv2.pyrMeanShiftFiltering(image, 11, 21)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.015 * peri, True)
if len(approx) == 4:
x,y,w,h = cv2.boundingRect(approx)
cv2.rectangle(image,(x,y),(x+w,y+h),(36,255,12),2)
cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()
I wound up just building on my original method and doing as Robert suggested in his comment on my question. After I get my list of rectangles, I then run through and calculate the average color over each rectangle. I check to see if the red, green, and blue components of the average color are each within 10% of the gray and blue rectangle colors, and if they are I save the rectangle, if they aren't I discard it. This process gives me something like this:
From this, it's trivial to get the information I need (orientation, starting point, and length of each rectangle, considering the game window as a 6x6 grid).
The blocks look like bitmaps - why don't you use simple template matching with different templates for each block size/color/orientation?
Since your problem is the small rectangles I would start by removing them.
Since those lines are much thinner than the borders of the rectangles I would start by applying morphological operations on the image.
Using a structural element that looks like this:
element = [ 1 1
1 1 ]
should remove lines that are less than two pixels wide. After the small lines are removed the rectangle finding algorithm of OpenCV will most likely do the rest of the job for you.
The erosion can be done in OpenCV by the function cvErode
Try one of the many corner detectors like harris corner detector. also it is in general a good idea to try that at multiple resolutions : so do some preprocessing of of varying magnification.
It appears that you want some sort of color dominated square then you can suppress the other colors, by first using something like cvsplit .....and then thresholding the color...so only that region remains....follow that with a cropping operation ...I think that could work as well ....
Given an object on a plain white background, does anybody know if OpenCV provides functionality to easily detect an object from a captured frame?
I'm trying to locate the corner/center points of an object (rectangle). The way I'm currently doing it, is by brute force (scanning the image for the object) and not accurate. I'm wondering if there is functionality under the hood that i'm not aware of.
Edit Details:
The size about the same as a small soda can. The camera is positioned above the object, to give it a 2D/Rectangle feel. The orientation/angle from from the camera is random, which is calculated from the corner points.
It's just a white background, with the object on it (black). The quality of the shot is about what you'd expect to see from a Logitech webcam.
Once I get the corner points, I calculate the center. The center point is then converted to centimeters.
It's refining just 'how' I get those 4 corners is what I'm trying to focus on. You can see my brute force method with this image: Image
There's already an example of how to do rectangle detection in OpenCV (look in samples/squares.c), and it's quite simple, actually.
Here's the rough algorithm they use:
0. rectangles <- {}
1. image <- load image
2. for every channel:
2.1 image_canny <- apply canny edge detector to this channel
2.2 for threshold in bunch_of_increasing_thresholds:
2.2.1 image_thresholds[threshold] <- apply threshold to this channel
2.3 for each contour found in {image_canny} U image_thresholds:
2.3.1 Approximate contour with polygons
2.3.2 if the approximation has four corners and the angles are close to 90 degrees.
2.3.2.1 rectangles <- rectangles U {contour}
Not an exact transliteration of what they are doing, but it should help you.
Hope this helps, uses the moment method to get the centroid of a black and white image.
cv::Point getCentroid(cv::Mat img)
{
cv::Point Coord;
cv::Moments mm = cv::moments(img,false);
double moment10 = mm.m10;
double moment01 = mm.m01;
double moment00 = mm.m00;
Coord.x = int(moment10 / moment00);
Coord.y = int(moment01 / moment00);
return Coord;
}
OpenCV has heaps of functions that can help you achieve this. Download Emgu.CV for a C#.NET wrapped to the library if you are programming in that language.
Some methods of getting what you want:
Find the corners as before - e.g. "CornerHarris" OpenCV function
Threshold the image and calculate the centre of gravity - see http://www.roborealm.com/help/Center%20of%20Gravity.php ... this is the method i would use. You can even perform the thresholding in the COG routine. i.e. cog_x += *imagePtr < 128 ? 255 : 0;
Find the moments of the image to give rotation, center of gravity etc - e.g. "Moments" OpenCV function. (I haven't used this)
(edit) The AForge.NET library has corner detection functions as well as an example project (MotionDetector) and libraries to connect to webcams. I think this would be the easiest way to go, assuming you are using Windows and .NET.
Since no one has posted a complete OpenCV solution, here's a simple approach:
Obtain binary image. We load the image, convert to grayscale, and then obtain a binary image using Otsu's threshold
Find outer contour. We find contours using findContours and then extract the bounding box coordinates using boundingRect
Find center coordinate. Since we have the contour, we can find the center coordinate using moments to extract the centroid of the contour
Here's an example with the bounding box and center point highlighted in green
Input image -> Output
Center: (100, 100)
Center: (200, 200)
Center: (300, 300)
So to recap:
Given an object on a plain white background, does anybody know if OpenCV provides functionality to easily detect an object from a captured frame?
First obtain a binary image (Canny edge detection, simple thresholding, Otsu's threshold, or Adaptive threshold) and then find contours using findContours. To obtain the bounding rectangle coordinates, you can use boundingRect which will give you the coordinates in the form of x,y,w,h. To draw the rectangle, you can draw it with rectangle. This will give you the 4 corner points of the contour. If you wanted to obtain the center point, use
moments to extract the centroid of the contour
Code
import cv2
import numpy as np
# Load image, convert to grayscale, and Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Find contours and extract the bounding rectangle coordintes
# then find moments to obtain the centroid
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
# Obtain bounding box coordinates and draw rectangle
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
# Find center coordinate and draw center point
M = cv2.moments(c)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
cv2.circle(image, (cx, cy), 2, (36,255,12), -1)
print('Center: ({}, {})'.format(cx,cy))
cv2.imshow('image', image)
cv2.waitKey()
It is usually called blob analysis in other machine vision libraries. I haven't used opencv yet.