I used this code to draw "Bounding boxes". Now I want the largest rectangle while there are many rectangles. After finding the largest rectangle, I want to have the coordinates of this rectangle. By these coordinates, I want to be a part of the original image.The largest rectangle is my car.
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
#include <iostream>
#include <sstream>
#include <fstream>
using namespace cv;
using namespace std;
Mat src; Mat src_gray;
int thresh = 0;
int max_thresh = 255;
RNG rng(12345);
/// Function header
void thresh_callback(int, void*);
/** #function thresh_callback */
void thresh_callback(int, void*)
{
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using Threshold
threshold(src_gray, threshold_output, thresh, 255, THRESH_BINARY);
/// Find contours
findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
/// Approximate contours to polygons + get bounding rects and circles
vector<vector<Point> > contours_poly(contours.size());
vector<Rect> boundRect(contours.size());
vector<Point2f>center(contours.size());
vector<float>radius(contours.size());
for (int i = 0; i < contours.size(); i++)
{
approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);
boundRect[i] = boundingRect(Mat(contours_poly[i]));
minEnclosingCircle((Mat)contours_poly[i], center[i], radius[i]);
}
/// Draw polygonal contour + bonding rects + circles
Mat drawing = Mat::zeros(threshold_output.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point());
rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
}
/// Show in a window
namedWindow("Contours", CV_WINDOW_AUTOSIZE);
imshow("Contours", drawing);
}
/** #function main */
int main(int argc, char** argv)
{
/// Load source image and convert it to gray
src = imread("RGB2YCrCb_BC_SB.png");
/// Convert image to gray and blur it
cvtColor(src, src_gray, CV_BGR2GRAY);
blur(src_gray, src_gray, Size(3, 3));
/// Create Window
char* source_window = "Source";
namedWindow(source_window, CV_WINDOW_AUTOSIZE);
imshow(source_window, src);
thresh_callback(0, 0);
waitKey(0);
return(0);
}
I have worked hard and I have searched a lot.Please help if you can.
See the picture.
Input image:
The result:
Src:
Find the max-area bounding-rect of approxed-poly-contours:
Cropped:
Code with comments:
//! 2018.05.13 13:31:34 CST
//! Find the max-area bounding-rect of approxed-poly-contours
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int findMaxRect(){
/// Read, cvtColor, threshold
Mat img, gray, threshed;
img = imread("car.jpg");
cvtColor(img, gray, COLOR_BGR2GRAY);
threshold(gray, threshed, 100, 255, THRESH_OTSU|THRESH_BINARY);
/// Find contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(threshed, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
/// Find the max boundingRect of approxed-contours
double max_area = -1;
Rect max_rect;
int idx = -1;
vector<Point2f> contour_poly;
for (int i = 0; i < contours.size(); i++){
/// Approx the contour
Mat contour = Mat(contours[i]);
double arclen = arcLength(contour, true);
approxPolyDP(contour, contour_poly, 0.03*arclen, true);
/// Get the bounding box
Rect rect = boundingRect(Mat(contour_poly));
/// Update the max_area_box
double area = rect.width*rect.height;
if(area>max_area){
max_area = area;
max_rect = rect;
}
}
cout << max_rect<<endl;
/// Draw the max rect
Mat drawing = img.clone();
rectangle(drawing, max_rect.tl(), max_rect.br(), Scalar(0,255,0), 1,8,0);
/// Crop
Mat dst = img(max_rect);
/// Display
imshow("drawing", drawing);
imshow("dst", dst);
waitKey(0);
return 0;
}
int main(int argc, char** argv){
//test_contours();
findMaxRect() ;
}
Related
I have a program to detect an Image using bounding box. But, somehow only the center of the image (which have a high saturation) can detect. I want to enlarge the bounding box so the object with low saturation can be detect too.Here is the image image result
The red rectangle is the result of boundingbox from findcontour. I want the rectangle like the blue one, so the large object can be detected. Here is my code:
#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
int main(){
Mat frame = imread("32.jpg", 1);
Mat mask(frame.size(), CV_8UC1, Scalar::all(0));
Mat hsv;
int a = 5;
cv::cvtColor(frame, hsv, CV_BGR2HSV);
std::vector<cv::Mat> channels;
split(hsv, channels);
cv::Mat H = channels[0];
cv::Mat S = channels[1];
cv::Mat V = channels[2];
Mat th;
threshold(S, th, 90, 255, THRESH_OTSU);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Find contours
findContours(th, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, Point(0, 0));
vector<Rect> rekt(contours.size());
/// Draw contours
Mat drawing = Mat::zeros(th.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{
if (cv::contourArea(contours[i]) < 500) continue;
rekt[i] = boundingRect(Mat(contours[i]));
rectangle(mask, rekt[i].tl(), rekt[i].br(), Scalar(0, 0, 255), 2, 8, 0);
}
imshow("ori", frame);
imshow("olaaa", resImage);
waitKey(0);
}
I have tried the other code such as here and this here but the image doesn't show the rectangle and only show black background.
Thankyou.
I've have a binary image computed from some algorithms. There is a hole in the image and I want to best fit a circle in this hole. I tried using bestminEnclosingCircle function but it don't give best results.
Here is binary image
Here is what I get from this function
Here is what expected
I want to exclude this part
Here is my code for finding contours
vector<Vec4i> hierarchy;
vector<vector<Point> > contours;
findContours(src, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
check the code below
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int, char** argv)
{
Mat src, src_gray;
/// Load source image and convert it to gray
src = imread("e:/test/ifFz9.png");
resize(src, src, Size(), 0.25, 0.25);
/// Convert image to gray and blur it
cvtColor(src, src_gray, COLOR_BGR2GRAY);
blur(src_gray, src_gray, Size(3, 3));
imshow("Source", src);
Mat threshold_output;
vector<vector<Point> > contours;
/// Detect edges using Threshold
threshold(src_gray, threshold_output, 127, 255, THRESH_BINARY);
/// Find contours
findContours(threshold_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);
for (size_t i = 0; i < contours.size(); i++)
{
if (contours[i].size() > 50)
{
RotatedRect minEllipse = fitEllipse(contours[i]);
int size = min(minEllipse.size.width, minEllipse.size.height) / 2;
// ellipse
if (size < src.rows / 2)
ellipse(src, minEllipse.center, Size(size, size), 0, 360, 0, Scalar(0, 0, 0255), 2, 8);
}
}
imshow("Contours", src);
waitKey(0);
return 0;
}
I have a image
this image is output of threshold function.
I want to detect the specified object as above and measure their heights.
My idea is extracting contours and use convex hull but my result not correct.
Have anyone idea for this problem?
regards.
Sys : Win7(64bit),OpenCV 3.1,Visual Studio 2015
my output :
here is my code:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
/// Function header
void thresh_callback(int, void*);
/** #function main */
int main(int argc, char** argv)
{
/// Load source image and convert it to gray
src = imread("C:/Users/Amin/Desktop/binary.jpg", 1);
/// Convert image to gray and blur it
cvtColor(src, src_gray, CV_BGR2GRAY);
blur(src_gray, src_gray, Size(3, 3));
/// Create Window
char* source_window = "Source";
namedWindow(source_window, CV_WINDOW_AUTOSIZE);
imshow(source_window, src);
createTrackbar(" Threshold:", "Source", &thresh, max_thresh, thresh_callback);
thresh_callback(0, 0);
waitKey(0);
return(0);
}
/** #function thresh_callback */
void thresh_callback(int, void*)
{
Mat src_copy = src.clone();
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using Threshold
threshold(src_gray, threshold_output, thresh, 255, THRESH_BINARY);
/// Find contours
findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
/// Find the convex hull object for each contour
vector<vector<Point> >hull(contours.size());
for (int i = 0; i < contours.size(); i++)
{
convexHull(Mat(contours[i]), hull[i], false);
}
/// Draw contours + hull results
Mat drawing = Mat::zeros(threshold_output.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point());
drawContours(drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point());
}
/// Show in a window
namedWindow("Hull demo", CV_WINDOW_AUTOSIZE);
imshow("Hull demo", drawing);
}
I achieved this result but don't know how to measure AB?
A is on the contour and B is known.
thanks
To measure heights (I think thats what you are asking?) there is little point in using Convex hull - considering this messy output. Instead, I would loop through each contour (1,2,3,4 and 5) and all their points, and detect the widths and heights separately by analysing the X,Y differences. so, while you loop through lets say contour 1, if Y is increasing but not X, you can assume it is the height .. so count each point. Then, when X starts to increase, assume the height has come to an end. You will want to set a tolerance as the lines are not perfectly straight. Hope this helps.
I try to detect license plate from image using OpenCV and C++. I can find the contours of license plate. But I want to drop only license plate. I have a idea to filter contours by bounding rect size.
Here is my code:
#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <opencv\ml.h>
#include <opencv\cxcore.h>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <stdio.h>
#include <stdlib.h>
#include<iostream>
using namespace cv;
using namespace std;
cv::Mat _img;
cv::Mat _imgGray;
int main()
{
_img = cv::imread("bs9.jpg");
if (_img.empty()) {
std::cout << "error: image not read from file\n\n";
return(0);
}
cv::Mat src;
medianBlur(_img, src, 9);
// chuyển ảnh gốc sang ảnh xám
cv::cvtColor(src, _imgGray, CV_BGR2GRAY);
cv::Mat _imgGray2;
medianBlur(_imgGray, _imgGray2, 7);
blur(_imgGray2, _imgGray2, Size(3, 3));
//Canny
cv::Mat edges;
//dalation
//cv::Canny(_imgGray, edges, 100, 250);
cv::Canny(_imgGray2, edges, 100, 200, 3);
//contour
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
//
//vector<Rect> boundRect(contours.size());
//CvMemStorage* stor = cvCreateMemStorage(1000);
findContours(edges, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// vẽ đường bao các cạnh
Mat drawing = Mat::zeros(edges.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(0,255,0);
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
}
//filter contour
????
/// show image
cv::imshow("Goc", _img); // show ảnh gốc
//
//cv::namedWindow("Anh xam", CV_WINDOW_AUTOSIZE);
cv::imshow("Xam", _imgGray); // show ảnh xám
cv::imshow("edges", edges); // show ảnh Canny
cv::imshow("contours", drawing);
cv::waitKey(0);
return(0);
}
You can use boundingRect(or boundingBox in some versions) Function in opencv to extract the bounding box of a contour.
int w_threshold = 100;
int h_threshold = 100;
vector<int> selected;
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(0, 255, 0);
Rect R = boundingRect(contours[i]);
// filter contours according to their bounding box
if (R.width > w_threshold && R.height > h_threshold)
{
selected.push_back(i);
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
}
}
//filter contour
/// show image
cv::imshow("Goc", _img); // show ảnh gốc
for (size_t i = 0; i < selected.size(); i++)
{
rectangle(_img, boundingRect(contours[selected[i]]), Scalar(0, 0, 255), 5);
}
cv::imshow("license candidates", _img); // show ảnh xám
and this was my output:
you can also use cvBlobLibs library. It has easy functions to manipulate blobs like what you want to do.
Here is my update code. I want to filter contours with ratio of width and height.
#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <opencv\ml.h>
#include <opencv\cxcore.h>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <opencv2\imgcodecs.hpp>
#include <stdio.h>
#include <stdlib.h>
#include<iostream>
using namespace cv;
using namespace std;
//khai báo biến
cv::Mat _img; // ảnh gốc
cv::Mat _imgGray; // ảnh xám
//hàm main
int main()
{
_img = cv::imread("bs9.jpg");
if (_img.empty()) {
std::cout << "error: image not read from file\n\n";
return(0);
}
cv::Mat src;
medianBlur(_img, src, 9);
// chuyển ảnh gốc sang ảnh xám
cv::cvtColor(src, _imgGray, CV_BGR2GRAY);
cv::Mat _imgGray2;
medianBlur(_imgGray, _imgGray2, 7);
blur(_imgGray2, _imgGray2, Size(3, 3));
//Canny
cv::Mat edges;
//dalation
//cv::Canny(_imgGray, edges, 100, 250);
cv::Canny(_imgGray2, edges, 100, 200, 3);
//contour
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(edges, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
//mới
vector<vector<Point> > contours_poly(contours.size());
vector<Rect> boundRect(contours.size());
vector<Point2f> ContArea(contours.size());
for (int i = 0; i < contours.size(); i++)
{
approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);
boundRect[i] = boundingRect(Mat(contours_poly[i]));
}
//mới
// vẽ đường bao các cạnh
Mat drawing = Mat::zeros(edges.size(), CV_8UC3);
//vector<Rect> boundRect(contours.size());
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(0,255,0);
//drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
drawContours(drawing, contours_poly, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point());
rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
}
//filter contour
/// show image
cv::imshow("Goc", _img); // show ảnh gốc
//
cv::imshow("Xam", _imgGray); // show ảnh xám
cv::imshow("edges", edges); // show ảnh Canny
cv::imshow("contours", drawing);
cv::waitKey(0);
return(0);
}
I am trying to find the dimension of different objects.
Until now I was working with one object. When I tried to find dimension of a different object, I realized that I needed to change threshold1 value of Canny.
So my question is: how can I make my program to do that kind of adjustments for different objects automatically? So that I won't need to change anything manually. What kind of algorithm should I use?
Background will be same, camera's position will be fixed, we can assume that the lighting will be same.
For this picture I need a threshold1 value of 53 in order to find the edges.
For this one, a value of 141 works pretty good.
I couldn't find any values for this one, since its color is almost same as the background's.
Here is my code:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
Mat src, src_gray, src_blur;
Mat canny_output;
int canny_thresh = 53;
int canny_max_thresh = 200;
int canny_kernel = 3;
int canny_ratio = 3;
bool L2gradient = true;
char* source_window = "Source";
char* canny_window = "Canny";
char* contour_window = "Contours";
/** #function main */
int main(int argc, char** argv)
{
/// Load source image and convert it to gray
src = imread("bluePaper2.png", 1);
/// Create Window
namedWindow(source_window, CV_WINDOW_AUTOSIZE);
imshow(source_window, src);
/// Convert image to gray and blur it
cvtColor(src, src_gray, CV_BGR2GRAY);
/// Reduce noise with a kernel 3x3
blur(src_gray, src_blur, Size(3, 3));
/// Detect edges using Canny
Canny(src_blur, canny_output, canny_thresh, canny_thresh * canny_ratio, canny_kernel, L2gradient);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Find contours
findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
/// Find the rotated rectangles and ellipses for each contour
vector<RotatedRect> minRect(contours.size());
vector<RotatedRect> minEllipse(contours.size());
for (int i = 0; i < contours.size(); i++)
{
minRect[i] = minAreaRect(Mat(contours[i]));
if (contours[i].size() > 5)
{
minEllipse[i] = fitEllipse(Mat(contours[i]));
}
}
/// Draw contours + rotated rects + ellipses
Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{
// contour
drawContours(drawing, contours, i, Scalar(255, 255, 0), 2, 8, vector<Vec4i>(), 0, Point());
// ellipse
ellipse(drawing, minEllipse[i], Scalar(0, 0, 255), 2, 8);
// rotated rectangle
Point2f rect_points[4]; minRect[i].points(rect_points);
for (int j = 0; j < 4; j++)
line(drawing, rect_points[j], rect_points[(j + 1) % 4], Scalar(0, 255, 0), 2, 8);
}
/// Show in a window
namedWindow(canny_window, CV_WINDOW_AUTOSIZE);
namedWindow(contour_window, CV_WINDOW_AUTOSIZE);
imshow(canny_window, canny_output);
imshow(contour_window, drawing);
waitKey(0);
return(0);
}