I'm working on a software using OpenCV for circles detection. I think that the most important problem is the image. Previously I try to detect circle by HoughCircles with bad results. After, I try to follow the instructions in this post but it doesn't work. Maybe I need some help to pre-processing image. Do anyone have any other ideas for detecting edges?
Original Image :
others similar images:
http://imgur.com/a/eSKFr
Below I have posted the code:
//Global variables
Mat src; Mat src_gray, threshold_output, element,dilated,eroded1, eroded2;
int thresh = 125;
int const max_value = 255;
int const max_BINARY_value = 255;
RNG rng(12345);
int s_ero1 =1;
int s_dil = 2;
int s_ero2 = 1;
int max_s = 50;
string source_window = "Thresh";
string TrackbarName = "Dilated";
string TrackbarName1 = "Eroded1";
string TrackbarName2 = "Eroded2";
/// Function header
void thresh_callback(int, void* );
void dilate_trackbar(int, void*);
void erode_trackbar1(int,void*);
void erode_trackbar2(int,void*);
int main( int, char** argv )
{
/// Load source image and convert it to gray
src = imread( "/media/Dati/image01.tif", 1 );
/// Convert image to gray and blur it
cvtColor( src, src_gray, COLOR_BGR2GRAY );
blur( src_gray, src_gray, Size(3,3) );
/// Create Window
namedWindow( "source", WINDOW_NORMAL );
imshow( "source", src );
waitKey();
namedWindow( source_window, WINDOW_NORMAL );
//Create trackbar threshold
createTrackbar( " Threshold:", source_window, &thresh, max_value, thresh_callback );
thresh_callback( 0, 0 );
waitKey();
namedWindow( TrackbarName1, WINDOW_NORMAL );
createTrackbar( "Size: ", TrackbarName1, &s_ero1, max_s, erode_trackbar1);
erode_trackbar1(0,0);
waitKey();
namedWindow( TrackbarName, WINDOW_NORMAL );
createTrackbar( "Size: ", TrackbarName, &s_dil, max_s, dilate_trackbar);
dilate_trackbar(0,0);
waitKey();
namedWindow( TrackbarName2, WINDOW_NORMAL );
createTrackbar( "Size: ", TrackbarName2, &s_ero2, max_s, erode_trackbar2);
erode_trackbar2(0,0);
waitKey();
return(0);
}
/**
* #function bounding_box
*/
void bounding_box(Mat m){
int max_point_pos = 0;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
// Find contours
findContours( m, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0) );
cout<<"Numero di blob: "<< contours.size()<<endl;
for(int i = 1; i < contours.size(); i++){
max_point_pos = contours[max_point_pos].size() > contours[i].size()? max_point_pos : i;
}
int max_point = contours[max_point_pos].size();
cout<< "il blob con più punti è associato alla posizione : " << max_point_pos << " con " << max_point << " punti"<< endl;
/// 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 + bounding rects + circles
Mat drawing = src.clone();
for( size_t i = 0; i< contours.size(); i++ )
{
if(contours[i].size() > 0.6*max_point){
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
//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 );
circle( drawing, center[i], (int)radius[i], color, 7, 8, 0 );
}
}
/// Show in a window
namedWindow( "Contours", WINDOW_NORMAL );
imshow( "Contours", drawing );
}
/**
* #function thresh_callback
*/
void thresh_callback(int, void* )
{
/// Detect edges using Threshold
threshold( src_gray, threshold_output, thresh, max_BINARY_value, THRESH_BINARY_INV);
imshow(source_window, threshold_output);
}
/**
* #function dilate_trackbar
* #brief Callback for trackbar
*/
void dilate_trackbar( int, void* )
{
dilated = threshold_output.clone();
element = getStructuringElement(MORPH_ELLIPSE,Size(s_dil, s_dil) , Point(-1,-1));
dilate(dilated,dilated,element,Point(-1,-1),1);
imshow(TrackbarName, dilated);
}
/**
* #function erode_trackbar
* #brief Callback for trackbar
*/
void erode_trackbar1( int, void*)
{
eroded1 = threshold_output.clone();
element = getStructuringElement(MORPH_ELLIPSE,Size(s_ero1, s_ero1) , Point(-1,-1));
erode(eroded1,eroded1,element,Point(-1,-1),1);
imshow(TrackbarName1, eroded1);
}
Related
I have this image :
And I applied dilation with this code :
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;
void Dilation( int, void* );
int main( int argc, char** argv )
{
src = imread("a18.png");
if( !src.data )
{ return -1; }
namedWindow( "Dilation Demo", CV_WINDOW_AUTOSIZE );
cvMoveWindow( "Dilation Demo", src.cols, 0 );
createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
&dilation_elem, max_elem,
Dilation );
createTrackbar( "Kernel size:\n 2n +1", "Dilation Demo",
&dilation_size, max_kernel_size,
Dilation );
//int dilation_size =7;
/// Default start
Dilation( 0, 0 );
waitKey(0);
return 0;
}
void Dilation( int, void* )
{
int dilation_type;
if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }
else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }
else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }
Mat element = getStructuringElement( dilation_type,
Size( 2*dilation_size + 1, 2*dilation_size+1 ),
Point( dilation_size, dilation_size ) );
dilate( src, dilation_dst, element );
imshow( "Dilation Demo", dilation_dst );
imwrite("a18d.png",dilation_dst);
}
And after this step I get this consequent:
And the final step is skeleton :
#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
int main()
{
cv::Mat img = cv::imread("a18d.png", 0);
cv::threshold(img, img, 127, 255, cv::THRESH_BINARY);
cv::Mat skel(img.size(), CV_8UC1, cv::Scalar(0));
cv::Mat temp;
cv::Mat eroded;
cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(3,3));
bool done;
do
{
cv::erode(img, eroded, element);
cv::dilate(eroded, temp, element); // temp = open(img)
cv::subtract(img, temp, temp);
cv::bitwise_or(skel, temp, skel);
eroded.copyTo(img);
done = (cv::countNonZero(img) == 0);
} while (!done);
cv::imshow("Skeleton", skel);
cv::imwrite("18s.png",skel);
cv::waitKey(0);
return 0;
}
code here
And I hve this image :
But I want image like this :
What can I do for this? What is the problem
these steps was done for Image 4 and result is good
Open CV doesn't seem to have a shrink as opposed to an erode operation. At least I can't find it. Try mine
https://github.com/MalcolmMcLean/binaryimagelibrary/blob/master/medialaxistransform.c
Try just using the function "thin" instead of eroding your image.
i have the following code :
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
String object_cascade_name = "haarcascade_frontalface_alt.xml";
CascadeClassifier object_cascade;
string window_name = "Capture - detector";
int main( void )
{
VideoCapture capture;
Mat frame;
std::vector<Rect> objects;
Mat frame_gray;
if( !object_cascade.load( object_cascade_name ) ){ std::cout << "ERROR: Cascade not loaded!\n" ; return -1; };
capture.open( 0 );
if( capture.isOpened() ){
for(;;){
capture >> frame;
capture.retrieve(frame);
//-- 3. Apply the classifier to the frame
if( !frame.empty() ){
// Start
cvtColor( frame, frame_gray, COLOR_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
//-- Detect Object
object_cascade.detectMultiScale( frame_gray, objects, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( size_t i = 0; i < objects.size(); i++ ){
Point pt1 = Point( objects[i].x, objects[i].y );
Point pt2 = Point( objects[i].x + objects[i].width, objects[i].y + objects[i].height );
rectangle( frame, pt1, pt2, Scalar( 34, 92, 241 ), 2, 8, 0 );
Mat faceROI = frame_gray( objects[i] );
}
//-- Show what you got
imshow( window_name, frame );
// End
}
else{ std::cout << "ERROR: frame.empty returns 1!"; break; }
int c = waitKey(10);
if( (char)c == 'c' ) { break; }
}
}
return 0;
}
which plays a video from the build-in webcam and detect faces, my idea is that i want the video to stop when an object -face- is detected, then display a window contains the detected object only from the last frame.
i am trying to run this OpenCV tutorial code using CodeBlocks on windows :
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
// Function Headers
void detectAndDisplay( Mat frame );
// Global variables
String face_cascade_name = "haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345);
// #function main
int main( int argc, const char** argv ){
CvCapture* capture;
Mat frame;
//-- 1. Load the cascades
if( !face_cascade.load( face_cascade_name ) ){ std::cout << "--(!)Error loading Face cascade\n"; return -1; };
if( !eyes_cascade.load( eyes_cascade_name ) ){ std::cout << "--(!)Error loading Eyes cascade\n"; return -1; };
//-- 2. Read the video stream
capture = cvCaptureFromCAM( 0 );
if( capture ){
while( true ){
frame = cvQueryFrame( capture );
//-- 3. Apply the classifier to the frame
if( !frame.empty() ){
detectAndDisplay( frame );
}
else{
std::cout << " --(!) No captured frame -- Break!"; break;
}
int c = waitKey(10);
if( (char)c == 'c' ) { break; }
}
}
return 0;
}
// #function detectAndDisplay
void detectAndDisplay( Mat frame ){
std::vector<Rect> faces;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
//-- Detect faces
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( size_t i = 0; i < faces.size(); i++ ){
Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
Mat faceROI = frame_gray( faces[i] );
std::vector<Rect> eyes;
//-- In each face, detect eyes
eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( size_t j = 0; j < eyes.size(); j++ ){
Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );
int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
circle( frame, center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 );
}
}
//-- Show what you got
imshow( window_name, frame );
}
But the Output is " --(!) No captured frame -- Break!"
During the execution the camera flash blinks then the output is displayed.
I have a function, with the following signature:
Mat cartoonifyImage( Mat, Mat );
I also have a VS2010 program as follows, where I apply to a webcam stream a number of filters, as taught in this book: Mastering OpenCV
int main( int argc, const char** argv )
{
VideoCapture camera;
camera.open(0);
if( !camera.isOpened() )
{
cerr << "Could not access the camera!" << endl;
return 1;
}
while( true )
{
Mat cameraFrame;
camera >> cameraFrame;
if( cameraFrame.empty() )
{
cerr << "Could not grab a camera frame!" << endl;
return 1;
}
// imshow( "Camera Test", cameraFrame );
Mat displayedFrame( cameraFrame.size(), CV_8UC3 );
cartoonifyImage( cameraFrame, displayedFrame );
imshow( "Cartoonifier!", displayedFrame );
int keypress = waitKey( 20 );
if( keypress == 27 ) break;
}
}
Here is my function definition:
Mat cartoonifyImage( Mat srcColor, Mat mask )
{
Mat gray, edges;
cvtColor( srcColor, gray, CV_BGR2GRAY );
const int MEDIAN_BLUR_FILTER_SIZE = 7;
const int LAPLACIAN_FILTER_SIZE = 5;
const int EDGES_THRESHOLD = 80;
medianBlur( gray, gray, MEDIAN_BLUR_FILTER_SIZE );
Laplacian( gray, edges, CV_8U, LAPLACIAN_FILTER_SIZE );
threshold( edges, mask, EDGES_THRESHOLD, 255, THRESH_BINARY_INV );
return( mask );
}
When I run the program, I get a blank (gray) window.
Where the first imshow is commented out, I made sure the webcam is working and I can see my own image in the window, so the problem must be elsewhere.
Can anyone help me understand where the problem is and what I am doing wrong?
Thank you,
your displayedFrame never got filled.
(you pass it into the func, it gets manipulated there, but since you gave it a copy, you don't get the result back)
either return a Mat from cartoonifyImage:
Mat displayed = cartoonifyImage( cameraFrame );
or pass references :
void cartoonifyImage( const Mat & cameraFrame, Mat & displayedFrame );
Mat cartoonifyImage( Mat srcColor )
{
Mat gray, edges, mask;
cvtColor( srcColor, gray, CV_BGR2GRAY );
const int MEDIAN_BLUR_FILTER_SIZE = 7;
const int LAPLACIAN_FILTER_SIZE = 5;
const int EDGES_THRESHOLD = 80;
medianBlur( gray, gray, MEDIAN_BLUR_FILTER_SIZE );
Laplacian( gray, edges, CV_8U, LAPLACIAN_FILTER_SIZE );
threshold( edges, mask, EDGES_THRESHOLD, 255, THRESH_BINARY_INV );
return ( mask );
}
int main( int argc, const char** argv )
{
VideoCapture camera;
camera.open(0);
if( !camera.isOpened() )
{
cerr << "Could not access the camera!" << endl;
return 1;
}
while( true )
{
Mat cameraFrame;
camera >> cameraFrame;
if( cameraFrame.empty() )
{
cerr << "Could not grab a camera frame!" << endl;
return 1;
}
//imshow( "Camera Test", cameraFrame );
Mat displayedFrame( cameraFrame.size(), CV_8UC3 );
displayedFrame = cartoonifyImage(cameraFrame);
imshow( "Cartoonifier!", displayedFrame );
int keypress = waitKey( 20 );
if( keypress == 27 ) break;
}
}
I am using OpenCV 2.4.6.
I am trying to get all the convexity defect depth_points of the biggest contour. But i am getting the bellow exception
Assertion failed (mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0)) in unknown function
the current code is pasted bellow
Thank you for any help
vector<vector<Point> >hulls( 1 );
vector<Point> hull;
std::vector<Vec4i> defects;
if(contours.size()>1){
convexHull( Mat(contours[largest_contour_index]), hulls[0], false );
convexityDefects(contours[largest_contour_index], hulls[0], defects);
drawContours(sourceVideo,contours,largest_contour_index,Scalar(255, 0, 0));
drawContours(sourceVideo,hulls,0,Scalar(0, 255, 0));
}
the error is in this line
convexityDefects(contours[largest_contour_index], hulls[0], defects);
Try this it works for me:
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <ctype.h>
#include <time.h>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
String window_name = "Hand_HSV";
Mat frame,copyFrame;
// Detect Skin from YCrCb
Mat DetectYCrCb(Mat img,Scalar min, Scalar max){
Mat skin;
cvtColor(img, skin, cv::COLOR_RGB2YCrCb);
inRange(skin, min, max, skin);
Mat rect_12 = getStructuringElement(cv::MORPH_RECT, Size(12,12) , Point(6,6));
erode(skin, skin, rect_12,Point(),1);
Mat rect_6 = getStructuringElement(cv::MORPH_RECT, Size(6,6) , Point(3,3));
dilate(skin,skin,rect_6,Point(),2);
return skin;
}
void DetectContour(Mat img){
Mat drawing = Mat::zeros( img.size(), CV_8UC3 );
vector<vector<Point> > contours;
vector<vector<Point> > bigContours;
vector<Vec4i> hierarchy;
findContours(img,contours, hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE, Point());
if(contours.size()>0)
{
vector<vector<int> >hull( contours.size() );
vector<vector<Vec4i>> convDef(contours.size() );
vector<vector<Point>> hull_points(contours.size());
vector<vector<Point>> defect_points(contours.size());
for( int i = 0; i < contours.size(); i++ )
{
if(contourArea(contours[i])>5000)
{
convexHull( contours[i], hull[i], false );
convexityDefects( contours[i],hull[i], convDef[i]);
// start_index, end_index, farthest_pt_index, fixpt_depth
for(int k=0;k<hull[i].size();k++)
{
int ind=hull[i][k];
hull_points[i].push_back(contours[i][ind]);
}
for(int k=0;k<convDef[i].size();k++)
{
if(convDef[i][k][3]>20*256)
{
int ind_0=convDef[i][k][0];
int ind_1=convDef[i][k][1];
int ind_2=convDef[i][k][2];
defect_points[i].push_back(contours[i][ind_2]);
cv::circle(drawing,contours[i][ind_0],5,Scalar(0,255,0),-1);
cv::circle(drawing,contours[i][ind_1],5,Scalar(0,255,0),-1);
cv::circle(drawing,contours[i][ind_2],5,Scalar(0,0,255),-1);
cv::line(drawing,contours[i][ind_2],contours[i][ind_0],Scalar(0,0,255),1);
cv::line(drawing,contours[i][ind_2],contours[i][ind_1],Scalar(0,0,255),1);
}
}
drawContours( drawing, contours, i, Scalar(0,255,0), 1, 8, vector<Vec4i>(), 0, Point() );
drawContours( drawing, hull_points, i, Scalar(255,0,0), 1, 8, vector<Vec4i>(), 0, Point() );
}
}
}
namedWindow( "Hull demo",cv::WINDOW_AUTOSIZE );
imshow( "Hull demo", drawing );
}
int main( int argc, char** argv )
{
VideoCapture capture(0);
//VideoCapture capture("Video_Hand.MPG");
namedWindow( window_name, cv::WINDOW_AUTOSIZE );
if (capture.isOpened()){
while(true)
{
capture >> frame;
imshow( window_name, frame);
Mat skinYCrCb = DetectYCrCb(frame,Scalar(0, 100, 80), Scalar(255, 185, 135));
imshow("Result",skinYCrCb);
DetectContour(skinYCrCb);
int c = waitKey(10);
if( (char)c == 27 )
{
break;
}
}
}
return 0;
}
Are you sure vector<vector<Point> >hulls is correct? The documentation (docs.opencv.org) mentions, for the 2nd parameter of convexityDefects:
convexhull – Convex hull obtained using convexHull() that should contain indices of the contour points that make the hull.
So i think it should be rather vector<vector<int> >hulls