I am right now working with OpenCV and Image processing. and Current topic that i am going through is, Convexity Defect. Following code that is simple program that can illustrates convexity defect, but i am getting error the error which is shown after the code. So please help me
Code :-
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
int g_thresh = 128;
int main(int argc, char **argv)
{
CvMemStorage *hull = cvCreateMemStorage(0);
CvMemStorage *mem = NULL;
CvMemStorage *defe_mem = cvCreateMemStorage(0);
mem = cvCreateMemStorage(0);
CvSeq *contours = NULL;
CvSeq *poly;
CvSeq *convex;
CvSeq *i;
CvSeq *defect;
IplImage *img = cvLoadImage(argv[1], CV_LOAD_IMAGE_COLOR);
IplImage *gray = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
cvCvtColor(img, gray, CV_RGB2GRAY);
cvShowImage("Source", img);
cvWaitKey(0);
cvShowImage("DEstination", gray);
cvWaitKey(0);
cvThreshold(gray, gray, g_thresh, 255, CV_THRESH_OTSU);
cvShowImage("BinaryImage", gray);
cvWaitKey(0);
int a = cvFindContours(gray, mem, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
cvDrawContours(gray, contours, cvScalarAll(255), cvScalarAll(255), 1, 1, 8, cvPoint(0, 0));
cvShowImage("Output",gray);
cvWaitKey(0);
convex = cvConvexHull2(contours, hull, CV_CLOCKWISE, 1);
cvDrawContours(gray, convex, cvScalarAll(255), cvScalarAll(255), 1, 1, 8, cvPoint(0, 0));
cvShowImage("Convex_Hull", gray);
cvWaitKey(0);
//Program Completely Works till here, every thing massed up after this line..
defect = cvConvexityDefects(contours, convex, defe_mem);
for( i = contours; i != 0; i = i->h_next){
cvDrawContours(gray, defect, cvScalarAll(255), cvScalarAll(255), 1, 1, 8, cvPoint(0, 0));
}
//fprintf(stderr, "Convexity Defect::%d\n", cvCheckContourConvexity(contours));
cvShowImage("Convexity", gray );
cvWaitKey(0);
}
Error :-
OpenCV Error: Unsupported format or combination of formats (Convex hull must represented as a sequence of indices or sequence of pointers) in cvConvexityDefects, file /home/akshit/OpenCV/OpenCV-2.4.3/modules/imgproc/src/convhull.cpp, line 544
terminate called after throwing an instance of 'cv::Exception'
what(): /home/akshit/OpenCV/OpenCV-2.4.3/modules/imgproc/src/convhull.cpp:544: error: (-210) Convex hull must represented as a sequence of indices or sequence of pointers in function cvConvexityDefects
Convex hull is found out properly with output, but convexity defect is not found out properly
Any Suggestion?
I think this code snippet should help:
#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.read(frame);
//flip(frame,frame,1);
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;
}
Related
I am sorry my bad english. I work with Raspberry pi 3's sample code. I try run sample code on Code Blocks and I work for learn. I configured debug setting based on Makefile of sample code. I configure linker setting. When I build the code on Code Blocks, it doesn't show error. But when I run code. I taked error on console. Error this:
Font_example: /home/pi/Desktop/Font_example/main.c: 101: main:Assertion 's==0' failed.
I remarked line. Code this:
// Test app for VG font library.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include "/opt/vc/src/hello_pi/libs/vgfont/bcm_host.h"
#include "/opt/vc/src/hello_pi/libs/vgfont/vgfont.h"
static const char *strnchr(const char *str, size_t len, char c)
{
const char *e = str + len;
do {
if (*str == c) {
return str;
}
} while (++str < e);
return NULL;
}
int32_t render_subtitle(GRAPHICS_RESOURCE_HANDLE img, const char *text, const int skip, const uint32_t text_size, const uint32_t y_offset)
{
uint32_t text_length = strlen(text)-skip;
uint32_t width=0, height=0;
const char *split = text;
int32_t s=0;
int len = 0; // length of pre-subtitle
uint32_t img_w, img_h;
graphics_get_resource_size(img, &img_w, &img_h);
if (text_length==0)
return 0;
while (split[0]) {
s = graphics_resource_text_dimensions_ext(img, split, text_length-(split-text), &width, &height, text_size);
if (s != 0) return s;
if (width > img_w) {
const char *space = strnchr(split, text_length-(split-text), ' ');
if (!space) {
len = split+1-text;
split = split+1;
} else {
len = space-text;
split = space+1;
}
} else {
break;
}
}
// split now points to last line of text. split-text = length of initial text. text_length-(split-text) is length of last line
if (width) {
s = graphics_resource_render_text_ext(img, (img_w - width)>>1, y_offset-height,
GRAPHICS_RESOURCE_WIDTH,
GRAPHICS_RESOURCE_HEIGHT,
GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
split, text_length-(split-text), text_size);
if (s!=0) return s;
}
return render_subtitle(img, text, skip+text_length-len, text_size, y_offset - height);
}
int main(void)
{
GRAPHICS_RESOURCE_HANDLE img;
uint32_t width, height;
int LAYER=1;
bcm_host_init();
int s;
s = gx_graphics_init(".");
assert(s == 0); //101. line
s = graphics_get_display_size(0, &width, &height);
assert(s == 0);
s = gx_create_window(0, width, height, GRAPHICS_RESOURCE_RGBA32, &img);
assert(s == 0);
// transparent before display to avoid screen flash
graphics_resource_fill(img, 0, 0, width, height, GRAPHICS_RGBA32(0,0,0,0x00));
graphics_display_resource(img, 0, LAYER, 0, 0, GRAPHICS_RESOURCE_WIDTH, GRAPHICS_RESOURCE_HEIGHT, VC_DISPMAN_ROT0, 1);
uint32_t text_size = 10;
while (1) {
const char *text = "The quick brown fox jumps over the lazy dog";
uint32_t y_offset = height-60+text_size/2;
graphics_resource_fill(img, 0, 0, width, height, GRAPHICS_RGBA32(0,0,0,0x00));
// blue, at the top (y=40)
graphics_resource_fill(img, 0, 40, width, 1, GRAPHICS_RGBA32(0,0,0xff,0xff));
// green, at the bottom (y=height-40)
graphics_resource_fill(img, 0, height-40, width, 1, GRAPHICS_RGBA32(0,0xff,0,0xff));
// draw the subtitle text
render_subtitle(img, text, 0, text_size, y_offset);
graphics_update_displayed_resource(img, 0, 0, 0, 0);
text_size += 1;
if (text_size > 50)
text_size = 10;
}
graphics_display_resource(img, 0, LAYER, 0, 0, GRAPHICS_RESOURCE_WIDTH, GRAPHICS_RESOURCE_HEIGHT, VC_DISPMAN_ROT0, 0);
graphics_delete_resource(img);
return 0;
}
1- What is wrong ?
2- Why this error on console why I couldn't see during on compiler?
NOTE: I can running this code on terminal (First go file and use make on console after use ./hello_font.bin) work fine.
Thanks your time. Best regards.
1- What is wrong ?
2- Why this error on console why I couldn't see during on compiler?
The assert you are using is a run-time assert.
If you want a compile-time assert, you have to use static_assert.
Using static_assert allows you to print your own message that will appear as compiler error.
Simple example:
int main()
{
static_assert(0 == 1, "Zero is not equal to one");
}
Compiler output:
main.cpp: In function 'int main()':
main.cpp:3:21: error: static assertion failed: Zero is not equal to one
static_assert(0 == 1, "Zero is not equal to one");
As in the comments of #Scheff. You should add macro. I added NDEBUG macro (on my project build setting and added macro to tab of other compiler under options). So my problem solved.
I have a video with a serial number. Like in the picture. How I can with openCV detect the position of this patron. The only thing that I need is detect the location of this patron. Always this patron will have 12 numbers and will be white.
example
using Morphological Transformations you can find location of numbers.
try the code below (not a perfect code, it is just for instruction)
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src=imread("dnpaP.jpg");
Mat thresh = src.clone();
dilate(thresh,thresh,Mat(),Point(-1,-1), 5);
erode(thresh,thresh,Mat(),Point(-1,-1), 5);
cvtColor(thresh, thresh, COLOR_BGR2GRAY);
threshold(thresh, thresh, 200, 255, THRESH_BINARY);
erode(thresh,thresh,Mat(),Point(-1,-1), 3);
dilate(thresh,thresh,Mat(),Point(-1,-1), 3);
vector<vector<Point> > contours;
findContours(thresh.clone(), contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
for( size_t i = 0; i< contours.size(); i++ )
{
Rect boundingRect_ = boundingRect( contours[i] );
if(boundingRect_.width > boundingRect_.height * 12)
rectangle(src,boundingRect_,Scalar(0,0,255),2);
}
imshow("thresh",thresh);
imshow("src",src);
waitKey();
}
I am using cvHoughCircles to find the two white ovals in the following image:
I first used thresholding for locating the white regions and then used Hough Transforms. But the output is not coming correct as shown below:
I am not able to understand what is happening? Why it is detecting 3 circles and why only one is being detected correctly? Any suggestions?
Below is my code:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include<conio.h>
#include<malloc.h>
using namespace cv;
using namespace std;
int main( ) {
IplImage* image = cvLoadImage(
"testing.bmp",
CV_LOAD_IMAGE_GRAYSCALE
);
IplImage* src = cvLoadImage("testing.bmp");
CvMemStorage* storage = cvCreateMemStorage(0);
cvThreshold( src, src, 200, 255, CV_THRESH_BINARY );
CvSeq* results = cvHoughCircles(
image,
storage,
CV_HOUGH_GRADIENT,
3,
image->width/10
);
for( int i = 0; i < results->total; i++ )
{
float* p = (float*) cvGetSeqElem( results, i );
CvPoint pt = cvPoint( cvRound( p[0] ), cvRound( p[1] ) );
cvCircle(
src,
pt,
cvRound( p[2] ),
CV_RGB(0xff,0,0)
);
}
cvNamedWindow( "HoughCircles", 1 );
cvShowImage( "HoughCircles", src);
cvWaitKey(0);
}
Edit:
Since I am not get satisfactory results with Hough Transform, I am willing to go for some other way. I can assume that each white blob in the figure is of equal size (size is known)and also the distance between the blob is known. Is there a non-trivial way I can find a vertical line (a tangent) touching the left side of left white blob? Once I know this tangent, I get an idea of the boundary location, then I will draw a circle at x=(this location + radius(which is known)), y= this location. Can I find such x and y coordinates using some non-trivial ways?
Solved, by changing as per below:
cvThreshold(image, image, 220, 255, CV_THRESH_BINARY );
cvCanny(image, image, 255, 255, 3);
cvNamedWindow( "edge", 1 );
cvShowImage( "edge", image);
cvWaitKey(0);
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* results = cvHoughCircles(
image,
storage,
CV_HOUGH_GRADIENT,
4,
image->width/4, 100,100,0,50);
Here is the output:
It's all about the parameters:
IplImage* src = cvLoadImage(argv[1]);
if (!src)
{
cout << "Failed: unable to load image " << argv[1] << endl;
return -1;
}
//IplImage* image = cvLoadImage(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
IplImage* image = cvCreateImage(cvSize(src->width, src->height), IPL_DEPTH_8U, 1);
cvCvtColor(src, image, CV_RGB2GRAY);
cvThreshold(image, image, 220, 255, CV_THRESH_BINARY );
// cvNamedWindow( "thres", 1 );
// cvShowImage( "thres", image);
// cvWaitKey(0);
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* results = cvHoughCircles(
image,
storage,
CV_HOUGH_GRADIENT,
4,
image->width/3);
std::cout << "> " << results->total << std::endl;
for( int i = 0; i < results->total; i++ )
{
float* p = (float*) cvGetSeqElem( results, i );
CvPoint pt = cvPoint( cvRound( p[0] ), cvRound( p[1] ) );
cvCircle(src,
pt,
cvRound( p[2] ),
CV_RGB(0xff,0,0));
}
cvNamedWindow( "HoughCircles", 1 );
cvShowImage( "HoughCircles", src);
cvWaitKey(0);
If you've done a little bit more experimentation you would have eventually found out that with different parameters you get different results:
You should use edge detected image as input, not the thresholded.
Secondly, Hough circles will not work for elipses, unless they are very close to circles. I recommend reading about Generalized Hough Transform and implementing it for ellipses.
I am trying to detect the face in the image and trying to save the detected face as an image in OpenCV.
Having some problems in the detectfaces function below.
#include "stdafx.h"
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
#include <cxcore.h>
CvHaarClassifierCascade *cascade;
CvMemStorage *storage;
void detectFaces( IplImage *img );
int _tmain(int argc, _TCHAR* argv[])
{
//CvCapture *capture;
IplImage *img;//*out;
int key = 0;
char *filename = "C:/OpenCV2.1/data/haarcascades/haarcascade_frontalface_alt.xml";
cascade = ( CvHaarClassifierCascade* )cvLoad( filename, 0, 0, 0 );
storage = cvCreateMemStorage( 0 );
img = cvLoadImage("Yurico.png");
assert( cascade && storage && img );
cvNamedWindow( "video:", 1 );
//cvNamedWindow( "video1:", 1 );
//out = detectFaces( img );
detectFaces( img );
cvWaitKey( 0 );
//cvShowImage( "video", out );
cvDestroyWindow( "video:" );
//cvDestroyWindow( "video1:" );
cvReleaseImage( &img );
cvReleaseHaarClassifierCascade( &cascade );
cvReleaseMemStorage( &storage );
return 0;
}
void detectFaces( IplImage *img )
{
int i;
CvRect *r;
CvSeq *faces = cvHaarDetectObjects(
img,
cascade,
storage,
1.1,
3,
0 /*CV_HAAR_DO_CANNY_PRUNNING*/,
cvSize( 40, 40) );
for( i = 0 ; i < ( faces ? faces->total : 0 ) ; i++ ) {
CvRect *r = ( CvRect* )cvGetSeqElem( faces, i );
cvRectangle( img,
cvPoint( r->x, r->y ),
cvPoint( r->x + r->width, r->y + r->height ),
CV_RGB( 255, 0, 0 ), 1, 8, 0 );
}
//cvShowImage( "video:", img );
cvSetImageROI(img, CvRect *r);
IplImage *img2 = cvCreateImage(cvGetSize(img),
img->depth,
img->nChannels);
cvSaveImage("Lakshmen.jpg",img2);
}
Have a error saying this :
Error 1 error C2664: 'cvSetImageROI' : cannot convert parameter 2 from 'CvRect *' to 'CvRect' c:\users\hp\documents\visual studio 2010\projects\facedetect\facedetect\facedetect.cpp 67 1 facedetect
Want to save the region of interest into another image. Any corrections or improvements do tell me..
you need to pass a CvRect and not a CvRect*, so you do not need the pointer (*) before r.
and since it is already a cvRect you should just write:
cvSetImageROI(img, &r);
cvSetImageROI() takes a cvRect as the 2nd argument, and it uses it as input parameter to clip the image to that area.
In other words, you need to create a cvRect with valid info. You can do it before calling the function, or inline:
cvSetImageROI(img_corr, cvRect(x_pos, y_pos, width, height));
I also noticed that in your code, you create CvRect* r; on at least 3 diferent locations inside the same function. Bad practice! Tip: create variables in your code at the moment you are going to use them, not before that.
Just replace the CvRect *r as r=(CvRect*)cvGetSeqElem( faces,i) and after the for-loop write the two lines
cvSetImageROI(img, cvRect(r->x,r->y,r->width,r->height));
cvSaveImage("C1.jpg",img);
I'm using opencv sequences to store points resulted from cvhoughline2.
I create the sequence and make some operations on it, but when I run the program it breaks in the line cvseqremove(seq,index) and gives me the exception:
exception at memory location
When I put the cursor on the seq in cvseqremove(seq,index), it writes to me: h_prev=0*000000000000000.
I wrote that code, i'll appreciate any help
void APPROXIMATE_LINES(IplImage* image,unsigned int xsize,unsigned int ysize,double width)
{
unsigned int i;
IplImage* color_dst = cvCreateImage(cvGetSize(image), 8,3);
IplImage* dst = cvCreateImage(cvGetSize(image), 8,1);
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* Filtered_Lines=0;
boolean isbreak;
double distance=4.0;
CvPoint Mid_Point;
CvPoint First_Mid_Point;
CvSeq* lines = cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),storage);
cvCanny(image,dst,180,250,3);
cvCvtColor(dst,color_dst,CV_GRAY2BGR);
lines = cvHoughLines2(dst, storage, CV_HOUGH_PROBABILISTIC, 4, CV_PI/165, 95, 93, 75);
while (lines->total>1)
{
CvPoint* First_Line = (CvPoint*)cvGetSeqElem(lines,0);
First_Mid_Point=mid(First_Line[0],First_Line[1]);
isbreak=FALSE;
for( i =1; i < lines->total; i++ )
{
CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
Mid_Point=mid(line[0],line[1]);
if(dist(First_Mid_Point.x,First_Mid_Point.y,Mid_Point.x,Mid_Point.y)<distance)
{
cvSeqRemove(lines,i);
isbreak=TRUE;
break;
}
} /*End_for*/
if(!isbreak)
{
cvSeqPushFront(Filtered_Lines,First_Line); // <--- breaks here
cvSeqRemove(lines,0);
}
} /*End_while*/
for(i=0;i<Filterd_Lines;i++)
{
CvPoint* Filtered = (CvPoint*)cvGetSeqElem(Filterd_Lines,i);
cvLine(color_dst, Filtered[0], Filtered[1], cvScalar(0,0,255,0),1,8,0);
}
cvNamedWindow( "Example1", CV_WINDOW_AUTOSIZE );
cvShowImage( "Example1",color_dst);
cvWaitKey(0);
cvReleaseImage( &color_dst);
cvDestroyWindow( "Example1" );
}
The function signature is:
void cvSeqRemove(CvSeq* seq, int index)
But on one part of the code you are doing:
cvSeqRemove(lines,&i);
Which means you are passing the memory address of the variable i instead of it's value, and this is not what you want to do.
There might be other bugs.