How to Enlarge each rectangle (boundingbox) from findcontour Opencv C++ - c++

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.

Related

How to detect triangle accurately in OpenCv using C++

I am detecting red triangle objects in real time video using OpenCv c++. But my program is not working properly. Whether I cannot use findContours or approxPolyDP not much well. Here is my code
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <raspicam/raspicam_cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int thresh = 100;
int number_pixels;
void drawAllTriangles(Mat&, const vector< vector<Point> >&);
int main(){
//Vectors
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
Mat canny_output,drawing;
//Initialise the image as a matrix container
Mat bgr;
raspicam::RaspiCam_Cv capture; // initialise the raspicam object
capture.open(); // activate the raspicam object
while (1)
{
capture.grab(); //grab the scene using raspicam
capture.retrieve(bgr); // retrieve the captured scene as an image and store it in matrix container
Mat gray,hsv; //Initialise the matrix container for gray color image
resize(bgr, bgr, Size(), .25, 0.25, CV_INTER_AREA);
//cvtColor(bgr, gray, COLOR_BGR2GRAY); //OpenCV code line for converting COLOR to GRAY scale image
//
cvtColor(bgr, hsv, COLOR_BGR2HSV);
//Gaussian Noice
Mat blure;
GaussianBlur(hsv,blure,Size(9,9),1.0);
//Gaussian Noice End
Mat mask1, mask2;
inRange(blure, Scalar(0,70,50), Scalar(10, 255, 255), mask1);
inRange(blure, Scalar(170, 70, 50), Scalar(180, 255, 255), mask2);
Mat mask3 = mask1 | mask2;
//Mat mask3 = mask1;
//
number_pixels = countNonZero(mask3);
Canny(mask3, canny_output, thresh, thresh*2, 3 );
findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
imshow("Original frame", bgr); //displaying original frame
imshow("Gray frame", mask3); //displaying original frame
drawAllTriangles(drawing,contours);
imshow("Triangles",drawing);
if (cvWaitKey(20) == 'q') // waitkey
break;
}
capture.release(); // release the raspicam frame grabbing
return 0;
}
void drawAllTriangles(Mat& img, const vector< vector<Point> >& contours){
vector<Point> approxTriangle;
for(size_t i = 0; i < contours.size(); i++){
approxPolyDP(contours[i], approxTriangle, arcLength(Mat(contours[i]), true)*0.05, true);
if(approxTriangle.size() == 3 and number_pixels>200){
drawContours(img, contours, i, Scalar(0, 255, 255), CV_FILLED); // fill GREEN
vector<Point>::iterator vertex;
for(vertex = approxTriangle.begin(); vertex != approxTriangle.end(); ++vertex){
circle(img, *vertex, 3, Scalar(0, 0, 255), 1);
}
printf("Triangle \n");
}
else {
printf("None \n");
}
}
}
My program should detect any red triangle shaped objects in video. Where I am going wrong. Thank you for answer
THese are the images, but it cannot detect triangles and confusing.

Creating Bounding boxes for contours

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() ;
}

Best fit a circle from a binary image using contours or any other technique

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;
}

detect fingers in hand

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.

OpenCV Skin Detection

I've been doing some skin detection but can't get a smooth one. The image below contains the input (left) and output (right) using the code also attached below. Now, the desired output should have been the bottom most image (the one that is smooth on the edges and doesn't have holes within). How do I achieve this output? A sample code on where to start would be of great help.
Input (left) and Incorrect output (right):
Desired output:
Code to generate the Incorect output:
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main(){
Mat src = imread("qq.jpg");
if (src.empty())
return -1;
blur( src, src, Size(3,3) );
Mat hsv;
cvtColor(src, hsv, CV_BGR2HSV);
Mat bw;
inRange(hsv, Scalar(0, 10, 60), Scalar(20, 150, 255), bw);
imshow("src", src);
imshow("dst", bw);
waitKey(0);
return 0;
}
Modified Code (after Astor's suggestion):
(the problem now is: how do you smoothen the output?)
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int findBiggestContour(vector<vector<Point> >);
int main(){
Mat src = imread("qq.jpg");
if (src.empty())
return -1;
blur( src, src, Size(3,3) );
Mat hsv;
cvtColor(src, hsv, CV_BGR2HSV);
Mat bw;
inRange(hsv, Scalar(0, 10, 60), Scalar(20, 150, 255), bw);
imshow("src", src);
imshow("dst", bw);
Mat canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours( bw, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
int s = findBiggestContour(contours);
Mat drawing = Mat::zeros( src.size(), CV_8UC1 );
drawContours( drawing, contours, s, Scalar(255), -1, 8, hierarchy, 0, Point() );
imshow("drw", drawing);
waitKey(0);
return 0;
}
int findBiggestContour(vector<vector<Point> > contours){
int indexOfBiggestContour = -1;
int sizeOfBiggestContour = 0;
for (int i = 0; i < contours.size(); i++){
if(contours[i].size() > sizeOfBiggestContour){
sizeOfBiggestContour = contours[i].size();
indexOfBiggestContour = i;
}
}
return indexOfBiggestContour;
}
You should use findContours to detect the biggest contour and after this draw founded contour with fill parameter -1 using method drawContours. Here's useful link: http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html
To improve the smoothness of the output, or in other words to reduce the black holes in the detected area try performing morphological operations on the resulting image.
Following documentation explains the eroding and dilating functions in opencv.
http://docs.opencv.org/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html