OpenCV not detect a circle in the picture - c++

I have a problem. I have the code:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
/** #function main */
int main(int argc, char** argv)
{
Mat src, src_gray;
/// Read the image
src = imread( argv[1], 1 );
if( !src.data )
{ return -1; }
/// Convert it to gray
cvtColor( src, src_gray, CV_BGR2GRAY );
/// Reduce the noise so we avoid false circle detection
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
vector<Vec3f> circles;
/// Apply the Hough Transform to find the circles
HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );
/// Draw the circles detected
for( size_t i = 0; i < circles.size(); i++ )
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// circle center
circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );
// circle outline
circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
/// Show your results
namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
imshow( "Hough Circle Transform Demo", src );
waitKey(0);
return 0;
}
This is an example from the website OpenCV ( http://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.html )
I have the following picture:
Image
For the image above code OpenCV does not detect the circle - circles.size() is equal 0.
What should I do? What to modify the code?

You're using the default thresholds (200 and 100) for an image with significant deviations from a circle (the solar flames). Not a programming error, just a data/settings issue.

Related

OpenCV C++: Convert big block of white pixels to black

I am new to OpenCV, so apologies if I am not able to express my issue properly.
So, I have an image that I converted to B&W. Now I want to convert all big block (block could be of any shapes) of white pixels to black and leave the small white pixels as it is.
To further explain, please look at the picture below:
This pic
This is from another stackoverflow post but basically what I want to do is get rid of that white box and just have text in my picture. In this picture, I can just put a black box on the top since I know where that white box is but how can I do it when I don't know where that white box is?
Thanks in advance
Edit: An example of a picture that I want is here
You can use minArearect function. This function draws fitted rectangles for each contour. You can filter by setting these rectangle edge lengths.
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
int main()
{
Mat src; Mat src_gray;
int thresh = 100;
RNG rng(12345);
/// Load source image and convert it to gray
src = imread( "/ur/src/image_directory/image.png", 1 );
Mat original = src.clone();
/// 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 );
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 rotated rectangles for each contour
vector<RotatedRect> minRect( contours.size() );
for( int i = 0; i < contours.size(); i++ )
minRect[i] = minAreaRect( Mat(contours[i]) );
int x1,x2,y1,y2;
/// Draw contours + rotated rects
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
Mat result_zero = 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) );
// contour
drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
// rotated rectangle
Point2f rect_points[4]; minRect[i].points( rect_points );
double length_1 = cv::norm(cv::Mat(rect_points[0]),cv::Mat(rect_points[1]));
double length_2 = cv::norm(cv::Mat(rect_points[1]),cv::Mat(rect_points[2]));
//This if scope for your desired rectangle size.You can set your size according to your rectangle(if it changes)
if(length_1>30 && length_1<100 && length_2>30 && length_2<100)
{
int min_x1 = INT_MAX, max_x2 = 0, min_y1 = INT_MAX, max_y2 = 0;
for( int j = 0; j < 4; j++ )
{
if(rect_points[j].x>max_x2 && rect_points[j].y>max_y2)
{
max_x2 = rect_points[j].x;
max_y2 = rect_points[j].y;
}
if(rect_points[j].x<min_x1 && rect_points[j].y<min_y1)
{
min_x1 = rect_points[j].x;
min_y1 = rect_points[j].y;
}
line( result_zero, rect_points[j], rect_points[(j+1)%4], color, 1, 8 );
}
x1 = min_x1;
x2 = max_x2;
y1 = min_y1;
y2 = max_y2;
}
}
circle(result_zero,Point(x1,y1),3,Scalar(0,255,255),2);
circle(result_zero,Point(x2,y2),3,Scalar(0,255,255),2);
// Here in source image we make the rectangle black according to found points
for(int i=y1-2;i<y2+2;i++)
{
for(int j=x1-2;j<x2+2;j++)
{
src.at<cv::Vec3b>(i,j)[0]=0;
src.at<cv::Vec3b>(i,j)[1]=0;
src.at<cv::Vec3b>(i,j)[2]=0;
}
}
/// Show in windows
namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
imshow("First",original);
imshow( source_window, result_zero );
imshow("Last",src);
imshow( "Contours", drawing );
waitKey(0);
return(0);
}
Source image:
Points:
Result:
Find contours.
For each contour: cv::Rect br = cv::boundingRect(contour)
bwImage(br) = cv::Scalar(0, 0, 0)

How can I get co ordinates(x,y values) of tracked object in opencv

I'm trying to track pupil iris by using open cv in c++.
I want coordinates of tracked pupil iris. How can I get it?
Right now I can tracked pupil iris, but I want coordinates as output in numbers. Which function can make this happen?
The code I've written until now is this:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/opencv.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
int main() {
VideoCapture cap(1); // open the default camera
cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 360);
if(!cap.isOpened()) // check if we succeeded
return -1;
namedWindow("Video",1);
Mat src_gray;
while(1) {
Mat frame,grey,edge,draw,src_gray;
cap >> frame;
cvtColor( frame, grey, CV_BGR2GRAY ); // get a new frame from camera
Canny( grey, edge, 50, 150, 3);
edge.convertTo(draw, CV_8U);
GaussianBlur( edge, src_gray, Size(9, 9), 2, 2 );
vector<Vec3f> circles;
HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 2, src_gray.rows/16, 80, 100, 30, 50 );
/// Draw the circles detected
for( size_t i = 0; i < circles.size(); i++ ) {
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// circle center
circle( src_gray, center, 3, Scalar(0,255,0), -1, 8, 0 );
// circle outline
circle( src_gray, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
Rect Rec(370,100,200,150);
rectangle(src_gray,Rec,Scalar(255),1,8,0);
namedWindow("roi",640*360);
Mat Roi=src_gray(Rec);
imshow("roi",Roi);
imshow("Video", src_gray);
// Press 'c' to escape
if(waitKey(30) == 'c') break;
}
return 0;
}

How can I get the color histogram inside the circle in the image or the gradient distribution in the circle?

I have detected circular objects in the image with OpenCV and C++ and using houghcircle function. But I would like to filter out only those circle that have dark color (it should be the airplane door window). So I thought to use the color histogram inside the detected circle in the image or the gradient distribution in those circle to filter out .It works on some images like in the image provided. But when there are more circles in the image does not find the dark circle. Also I played with canny threshold but I would like it do happened automatically. So basically how to make the program more robust?
Firstly here is the code in C++ using OpenCV and C++
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
#include <vector>
int thresh = 200;
int max_thresh = 400;
Mat src;
void thresh_callback(int, void* );
int main()
{
cv::Mat src = cv::imread("d4.png");
resize(src, src, Size(640,480), 0, 0, INTER_CUBIC);
char* source_window = "Source";
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
imshow( source_window, src );
createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );
thresh_callback( 0, 0 );
waitKey(0);
return(0);
}
void thresh_callback(int, void* ) {
Mat src_gray;
cv::Mat bgr_image = cv::imread( "d4.png");
cv::Mat orig_image = bgr_image.clone();
cvtColor( bgr_image, src_gray, COLOR_BGR2HSV );
medianBlur(src_gray, src_gray, 3);
Mat canny_output;
Canny( src_gray, canny_output, thresh, thresh*3.5, 3 );
// Threshold the HSV image, keep only the black pixels
cv::Mat lower_black_hue_range;
cv::Mat upper_black_hue_range;
cv::inRange(canny_output, cv::Scalar(0, 0, 0), cv::Scalar(10, 10, 40), lower_black_hue_range);
cv::inRange(canny_output, cv::Scalar(0,0, 41), cv::Scalar(10, 15, 50), upper_black_hue_range);
// Combine the above two images
cv::Mat black_hue_image;
cv::addWeighted(lower_black_hue_range, 1.0, upper_black_hue_range, 1.0, 0.0, black_hue_image);
cv::GaussianBlur(black_hue_image, black_hue_image, cv::Size(9, 9), 2, 2);
// Use the Hough transform to detect circles in the combined threshold image
std::vector<cv::Vec3f> circles;
cv::HoughCircles(black_hue_image, circles, CV_HOUGH_GRADIENT, 1, black_hue_image.rows/1, 10, 100, 10, 0);
// Loop over all detected circles and outline them on the original image
if(circles.size() == 0) std::exit(-1);
for(size_t current_circle = 0; current_circle < circles.size(); ++current_circle) {
Point center(cvRound(circles[current_circle][0]), cvRound(circles[current_circle][1]));
int radius = cvRound(circles[current_circle][2]);
cv::circle(orig_image, center, radius, cv::Scalar(0, 255, 0), 5);
}
// Show images
resize(lower_black_hue_range, lower_black_hue_range, Size(640,480), 0, 0, INTER_CUBIC);
char* source_window1 = "Threshold lower image";
namedWindow( source_window1, CV_WINDOW_AUTOSIZE );
imshow( source_window1, lower_black_hue_range );
//cv::namedWindow("Threshold lower image", cv::INTER_CUBIC);
//cv::imshow("Threshold lower image", lower_black_hue_range);
resize(upper_black_hue_range, upper_black_hue_range, Size(640,480), 0, 0, INTER_CUBIC);
char* source_window2 = "Threshold upper image";
namedWindow( source_window2, CV_WINDOW_AUTOSIZE );
imshow( source_window2, lower_black_hue_range );
//cv::namedWindow("Threshold upper image", cv::INTER_CUBIC);
//cv::imshow("Threshold upper image", upper_black_hue_range);
resize(black_hue_image, black_hue_image, Size(640,480), 0, 0, INTER_CUBIC);
char* source_window3 = "Combined threshold images";
namedWindow( source_window3, CV_WINDOW_AUTOSIZE );
imshow( source_window3, black_hue_image );
//cv::namedWindow("Combined threshold images", cv::INTER_CUBIC);
//cv::imshow("Combined threshold images", black_hue_image);
resize(orig_image, orig_image, Size(640,480), 0, 0, INTER_CUBIC);
char* source_window4 = "Detected black circles on the input image";
namedWindow( source_window4, CV_WINDOW_AUTOSIZE );
imshow( source_window4, orig_image );
//cv::namedWindow("Detected black circles on the input image", cv::INTER_CUBIC);
//cv::imshow("Detected black circles on the input image", orig_image);
}
Input image of good detected circle
The output is correct
Second image with more circles
The output is wrong, wrong detected circle
Any help?

Hough algorithm don't find outer circle when there is a circle inside

I use hough transform to find circles in my picture, but it doesn't find outer circle.( I use opencv 2.4.2 and QT 3.3.0)
my code:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
int HoughCircle1()
{
Mat src,dst, src_gray;
/// Read the image
src = imread("E:/imagesForImgProc/test.jpg",CV_LOAD_IMAGE_COLOR);
if( !src.data )
{
return -1;
}
/// Reduce the size of image
Size size(src.cols/2,src.rows/2);
resize(src, dst,size, 0, 0, CV_INTER_LINEAR);
/// Convert it to gray
cvtColor( dst, src_gray, CV_BGR2GRAY );
/// Reduce the noise so we avoid false circle detection
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
/// Apply the Hough Transform to find the circles
vector<Vec3f> circles;
HoughCircles( src_gray, circles,CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );
/// Draw the circles detected
for( size_t i = 0; i < circles.size(); i++ )
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
/// circle center
circle( dst, center, 3, Scalar(0,255,0), -1, 8, 0 );
/// circle outline
circle( dst, center, radius, Scalar(0,0,255), 1, 8, 0 );
}
/// Show your results
namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
imshow( "Hough Circle Transform Demo", dst );
return 0;
}
int main()
{
HoughCircle1();
waitKey(0);
return 0;
}
"Orginal image"
"Code result "
"Wanted result"

Retrieving outer contour of an object

I am newbie in programming, so please help me. I want to retrieve only the outer contour of an object but the problem is I got another contour like a border. How can I get the only outer contour of object without any other contour?
An example image:
Here is the code I made:
// cvAutoHeight.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "opencv\cvaux.h"
#include "opencv\cxmisc.h"
#include "opencv\highgui.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdlib.h>
using namespace std;
using namespace cv;
int main(int, char**)
{
Mat threshold_output;
int thresh = 100;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
RNG rng(12345);
CvCapture* capture = cvCaptureFromCAM(0);
cv::Mat frame; cv::Mat src_gray;
while(1) {
frame = cvQueryFrame( capture );
cvtColor( frame,src_gray, CV_BGR2GRAY );
blur( src_gray, src_gray, Size(3,3) );
//Canny( src_gray, threshold_output, 128, 255, 3 );
threshold( src_gray, threshold_output, 100, 200, THRESH_BINARY );
findContours( threshold_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() );
for( int i = 0; i < contours.size(); i++ )
{
minRect[i] = minAreaRect( Mat(contours[i]) );
}
/// Draw contours + rotated rects + ellipses
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0,0), rng.uniform(0,0), rng.uniform(250,250) );
// contour
drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0,
Point() );
// rotated rectangle
Point2f rect_points[4]; minRect[i].points( rect_points );
for( int j = 0; j < 4; j++ )
line( frame, rect_points[j], rect_points[(j+1)%4], color, 1, 8 );
}
namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
imshow( "Contours", frame );
cvWaitKey(33);
}
return 0;
}
`
by default, out of borders have 0 pixel value = black. after threshold, you get your black blob with white background. this why you have 2 contours. choose one of the solutions:
use binary threshold inverted.
apply canny after threshold.