c++ opencv find center of object and add circle - c++

Hi I am trying to learn opencv . with this code ı am trying to put circle to center of objects . When ı try to write 1,2,3 etc it is okey but when ı try to add circle to center of object it is problem. .
My code:
void findcontours(){
cv::namedWindow("contourdemo",CV_GUI_EXPANDED);
src = cv::imread("/home/zugurtaga/Desktop/project/opencv/imgs/seed.jpg");
if(src.data){
if(src.channels() > 1){
cv::cvtColor(src,src,CV_RGB2GRAY);
}else {
src = src;
}
cv::Mat cImc = src.clone();
cv::threshold(cImc,cImc,150,255,CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
cv::imshow("contourdemo",cImc);
cv::waitKey(0);
vector<vector <cv::Point> > contours;
vector<cv::Point> contPoly;
vector<cv::Vec4i> hierarchy;
cv::findContours(cImc,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);
cout << "Number of counts: " << contours.size() << endl;
tmp = cv::Mat::zeros(cImc.size(),CV_8UC3);
cv::RotatedRect rRect;
//Problem line ???
shapeMoments = cv::moments(contours);
cv::HuMoments(shapeMoments,shapeHumoments);
centerofmass.x = (shapeMoments.m10 / shapeMoments.m00);
centerofmass.y = (shapeMoments.m01 / shapeMoments.m00);
cout << "centerofmass.x: " << centerofmass.x << " centerofmass.y: " << centerofmass.y << endl;
// till here
for (size_t i = 0; i < contours.size(); i++) {
cv::drawContours(tmp,contours,i,cv::Scalar(120,0,0),CV_FILLED,8,hierarchy,0,cv::Point());
rRect = cv::minAreaRect(contours[i]);
cv::putText(tmp,cv::format("%d",i+1),rRect.center,1,1,cv::Scalar(255,255,255));
cv::circle(tmp,centerofmass,(int)3,cv::Scalar(255,255,255),-1,8,0);
}
cv::imshow("contourdemo",tmp);
cv::waitKey(0);
cv::destroyAllWindows();
}else{
cout << "No file.." << endl;
}
}
Thanks for any help.

ı found problem after some trying this is working.
for (size_t i = 0; i < contours.size(); i++) {
shapeMoments = cv::moments(contours[i]);
cv::HuMoments(shapeMoments,shapeHumoments);
centerofmass.x = (shapeMoments.m10 / shapeMoments.m00);
centerofmass.y = (shapeMoments.m01 / shapeMoments.m00);
cout << "centerofmass.x: " << centerofmass.x << " centerofmass.y: " << centerofmass.y << endl;
cv::drawContours(tmp,contours,i,cv::Scalar(120,0,0),CV_FILLED,8,hierarchy,0,cv::Point());
rRect = cv::minAreaRect(contours[i]);
cv::putText(tmp,cv::format("%d",i+1),centerofmass,1,1,cv::Scalar(255,255,255));
cv::circle(tmp,centerofmass,(int)3,cv::Scalar(255,255,255),-1,8,0);
}

Related

How to identify stranger in dlib`s one vs one classifier

I`m using a one_vs_one_trainer and one_vs_one_decision_function for classify 128D face descriptors, and i want to detect unknown face.
I`m detecting faces using OpenCV and my wrapper, then i followed the guide and computed the 128D face descriptors, that i stored in files. Next, i trained one_vs_one classifier following this tutorial. All works perfectly, but when i try to classify unknown face it returns some label.
I used code from guides, but if you want to look at my code - it is here
Is there a better way to identify faces? Maybe, its simpler to use OpenCV`s methods, or other from Dlib?
Thanks for Davis!
Here is forum thread on SourceForge.
The answer is:
Use a bunch of binary classifiers rather than one vs one. If all the binary
classifiers say they don't match then you know the person doesn't match any
of them.
And i implemented this as follows:
#include <iostream>
#include <ctime>
#include <vector>
#include <dlib/svm.h>
using namespace std;
using namespace dlib;
int main() {
typedef matrix<double, 128, 1> sample_type;
typedef histogram_intersection_kernel<sample_type> kernel_type;
typedef svm_c_trainer<kernel_type> trainer_type;
typedef decision_function<kernel_type> classifier_type;
std::vector<sample_type> samples;
std::vector<double> labels;
sample_type sample;
// Samples ->
sample = -0.104075,0.0353173,...,0.114782,-0.0360935;
samples.emplace_back(sample);
labels.emplace_back(0);
sample = -0.0842,-0.0103397,...,0.0938285,0.010045;
samples.emplace_back(sample);
labels.emplace_back(0);
sample = -0.0978358,0.0709425,...,0.052436,-0.0582029;
samples.emplace_back(sample);
labels.emplace_back(0);
sample = -0.126522,0.0319873,...,0.12045,-0.0277105;
samples.emplace_back(sample);
labels.emplace_back(0);
sample = -0.10335,-0.0261625,...,0.0600661,0.00703168,-8.67462e-05,-0.0598214,-0.104442,-0.046698,0.0553857,-0.0880691,0.0482511,0.0331484;
samples.emplace_back(sample);
labels.emplace_back(0);
sample = -0.0747794,0.0599716,...,-0.0440207,-6.45183e-05;
samples.emplace_back(sample);
labels.emplace_back(1);
sample = -0.0280804,0.0900723,...,-0.0267513,0.00824318;
samples.emplace_back(sample);
labels.emplace_back(1);
sample = -0.0721213,0.00700722,...,-0.0128318,0.100784;
samples.emplace_back(sample);
labels.emplace_back(1);
sample = -0.122747,0.0737782,0.0375799,...,0.0168201,-0.0246723;
samples.emplace_back(sample);
labels.emplace_back(1);
sample = -0.0218071,0.118063,...,-0.0735178,0.04046;
samples.emplace_back(sample);
labels.emplace_back(1);
sample = -0.0680787,0.0490121,-0.0228516,...,-0.0366242,0.0287891;
samples.emplace_back(sample);
labels.emplace_back(2);
sample = 0.00152394,0.107174,...,-0.0479925,0.0182667;
samples.emplace_back(sample);
labels.emplace_back(2);
sample = -0.0334521,0.165314,...,-0.0385227,-0.0215499;
samples.emplace_back(sample);
labels.emplace_back(2);
sample = 0.0276394,0.106774,...,-0.0496831,-0.020857;
samples.emplace_back(sample);
labels.emplace_back(2);
// <- Samples
// Unique labels ->
std::vector<double> total_labels;
for(double &label : labels) {
if(find(total_labels.begin(), total_labels.end(), label) == total_labels.end())
total_labels.emplace_back(label);
}
// <- Unique labels
// Init trainers ->
std::vector<trainer_type> trainers;
int num_trainers = total_labels.size() * (total_labels.size() - 1) / 2;
cout << "Number of trainers is " << num_trainers << endl;
for(int i = 0; i < num_trainers; i++) {
trainers.emplace_back(trainer_type());
trainers[i].set_kernel(kernel_type());
trainers[i].set_c(10);
}
// <- Init trainers
// Init classifiers ->
std::vector<pair<double, double>> classifiersLabels;
std::vector<classifier_type> classifiers;
int label1 = 0, label2 = 1;
for(trainer_type &trainer : trainers) {
std::vector<sample_type> samples4pair;
std::vector<double> labels4pair;
for(int i = 0; i < samples.size(); i++) {
if(labels[i] == total_labels[label1]) {
samples4pair.emplace_back(samples[i]);
labels4pair.emplace_back(-1);
}
if(labels[i] == total_labels[label2]) {
samples4pair.emplace_back(samples[i]);
labels4pair.emplace_back(+1);
}
}
classifiers.emplace_back(trainer.train(samples4pair, labels4pair));
classifiersLabels.emplace_back(make_pair(total_labels[label1],
total_labels[label2]));
label2++;
if(label2 == total_labels.size()) {
label1++;
label2 = label1 + 1;
}
}
// <- Init classifiers
double threshold = 0.3;
auto classify = [&](){
std::map<double, int> votes;
for(int i = 0; i < classifiers.size(); i++) {
cout << "Classifier #" << i << ":" << endl;
double prediction = classifiers[i](sample);
cout << prediction << ": ";
if(abs(prediction) < threshold) {
cout << "-1" << endl;
} else if (prediction < 0) {
votes[classifiersLabels[i].first]++;
cout << classifiersLabels[i].first << endl;
} else {
votes[classifiersLabels[i].second]++;
cout << classifiersLabels[i].second << endl;
}
}
cout << "Votes: " << endl;
for(auto &vote : votes) {
cout << vote.first << ": " << vote.second << endl;
}
auto max = std::max_element(votes.begin(), votes.end(),
[](const pair<double, int>& p1, const pair<double, int>& p2) {
return p1.second < p2.second; });
double label = votes.empty() ? -1 : max->first;
cout << "Label is " << label << endl;
};
// Test ->
cout << endl;
sample = -0.0971093, ..., 0.123482, -0.0399552;
cout << "True: 0 - " << endl;
classify();
cout << endl;
sample = -0.0548414, ..., 0.0277335, 0.0460183;
cout << "True: 1 - " << endl;
classify();
cout << endl;
sample = -0.0456186,0.0617834,...,-0.0387607,0.0366309;
cout << "True: 1 - " << endl;
classify();
cout << endl;
sample = -0.0500396, 0.0947202, ..., -0.0540899, 0.0206803;
cout << "True: 2 - " << endl;
classify();
cout << endl;
sample = -0.0702862, 0.065316, ..., -0.0279446, 0.0453012;
cout << "Unknown - " << endl;
classify();
cout << endl;
sample = -0.0789684, 0.0632067, ..., 0.0330486, 0.0117508;
cout << "Unknown - " << endl;
classify();
cout << endl;
sample = -0.0941284, 0.0542927, ..., 0.00855513, 0.00840678;
cout << "Unknown - " << endl;
classify();
// <- Test
return 0;
}

how to capture images per second from video files by using opencv and c++?

I have encountered on designing program to allow capturing images every second from video files (avi, mp4, etc...).
First, I was able to capture images frame by frame from video file.
Second, I was able to analyze pixel color values from images in the same folder at the same time and saved pixel value in the txt file.
And here I have some problem. I am now trying to combine these two codes at once, but I have strange results. I refer the code below.
int main(){
VideoCapture cap("D:\\data\\extra\\video200ul.avi");
if (!cap.isOpened())
return -1;
Ptr<BackgroundSubtractor> pMOG2 = createBackgroundSubtractorMOG2(20, 16, true);
Mat fg_mask;
Mat frame;
int count = 0;
String name, folder;
for (;;) {
// Get frame
cap >> frame; // get a new frame from video
++count;
// Update counter
// Background subtraction
if (count % 2 == 0) {
pMOG2->apply(frame, fg_mask, 0.001);
cout << count << endl;
if (!frame.empty()) {
imshow("frame", frame);
// imshow("fg_mask", fg_mask);
}
// Save foreground mask
name = "mask" + std::to_string(count) + ".png";
// string name = "mask_" + std::to_string(static_cast<long long>(count) + ".png";
folder = imwrite("D:\\data\\extra\\" + name, frame);
}
anal(folder);
}
waitKey(0);
return 0;
}
First, The code above I wrote is for capturing images frame by frame from video file. However, if I got the images per frame, I will have so many pictures on my folder, so I would like to capture an image per second from the video file. I have tried to use CV_CAP_PROP_POS_MSEC instead using cap << frame, but it did not work for me.
Second, when I merge this code to another code what I wrote below, it showed some error messages like, "libpng warning image width, length, data are zero in ihdr."
int anal(String folder) {
folder = "D:\\data\\extra\\*.png";
vector<String> filenames;
glob(folder, filenames);
cv::Mat ori_image;
for (size_t i = 0; i < filenames.size(); ++i) {
ori_image = imread(filenames[i], IMREAD_COLOR);
if (ori_image.empty()) {
cout << "Check your file again." << std::endl;
return -1;
}
rectangle(ori_image, Point(215, 98), Point(245, 110), Scalar(0, 255, 255), 1);
imshow("Original Image", ori_image);
cv::Scalar sums;
sums = cv::sum(ori_image);
double totalSum = sums[0] + sums[1] + sums[2];
if (totalSum <= 0) {
cout << "$$ RGB percentage $$" << " \n\n";
cout << "R: " << 100.0 / 3 << " % \n";
cout << "G: " << 100.0 / 3 << " % \n";
cout << "B: " << 100.0 / 3 << " % \n\n";
}
else {
cout << "$$ RGB percentage $$" << " \n\n"; // red value
cout << "R: " << sums[2] / totalSum * 100 << " % \n"; // red value
cout << "G: " << sums[1] / totalSum * 100 << " % \n"; // green value
cout << "B: " << sums[0] / totalSum * 100 << " % \n\n"; // blue value
}
}
as I prepared the code above, I tried to calculate red, blue, green percentages of all the captured images from the video. However, when I separate these two code and run them, they worked fine, but if I merge them together, It showed error messages.
I would like to combine these two code for analysis for color values from the captured images at video every second.
Please help me out this problem.
Thank you in advance.
-----------Edited part----------------------
I used your revised version and applied to my updated code,
void imageAnalysis(std::string folder, cv::Mat frame){
cv::Mat ori_image = frame.clone();
std::string path = folder;
cv::rectangle(ori_image, Point(215, 105), Point(245, 120), Scalar(0, 255, 255), 1);
cv::imshow("Original Image", ori_image);
cv::waitKey(1);
String folder = "D:\\data\\dfdf\\*.png";
vector<String> filenames;
cv::glob(path, filenames);
for (size_t t = 0; t < filenames.size(); t++) {
ori_image = imread(filenames[t], IMREAD_COLOR); // ori_image
if (ori_image.empty()) { //ori_image
cout << "Check your file again." << "\n";
break;
//return -1;
}
rectangle(ori_image, Point(215, 105), Point(245, 120), Scalar(0, 255, 255), 1);
imshow("Original Image", ori_image);
cv::waitKey(1);
Mat image_HSV;
cvtColor(ori_image, image_HSV, CV_BGR2HSV);
double h = 0.0;
double s = 0.0;
double v = 0.0;
int col = image_HSV.cols; // 480
int row = image_HSV.rows; // 272
int corow = ((col - 235) - 215) * ((row - 152) - 108);
Mat mask;
inRange(image_HSV, Scalar(100, 0, 0), Scalar(100, 255, 255), mask); // convert binary
image_HSV.setTo(Scalar(0, 0, 0), mask);
for (int i = 108; i < row - 152; i++) {
for (int j = 215; j < col - 235; j++) {
Vec3b hsv = image_HSV.at<cv::Vec3b>(i, j);
h += (int)(hsv.val[0]);
s += (int)(hsv.val[1]);
v += (int)(hsv.val[2]);
if (hsv[0] != 100) {
hsv[0] = 0;
hsv[1] = 0;
hsv[2] = 0;
}
}
}
cout << "$$ Hue(H), Saturation(S), Brightness(V) $$" << filenames[t] << " !! \n\n";
cout << "H: " << h / corow * 360 / 180 << " % \n"; //
cout << "S: " << s / corow * 100 / 255 << " % \n";
cout << "V: " << v / corow * 100 / 255 << " % \n\n";
std::ofstream file("D:\\data\\dfdf\\result_4.txt", std::ios_base::app);
file << v / corow * 100 / 255 << " \n"; // v value
file.close();
}
}
As you can see the imageAnalysis() function, I added std::string folder for the path of extracted images from video clip. However, when I applied this code, I have really weird results like below..
enter image description here
I thought I am supposed to get color value from every 24th image but as you see the results above, I got color values from all images in random order.
Thank you in advance.
It was really nice to learn how to code in efficient way!!
Just to clear the error you mentioned about CV_CAP_PROP_POS_MSEC in your comments:
when I apply CV_CAP_PROP_POS_MSEC to my code, I found some error
messages like "CV_CAP_PROP_POS_MSEC is not defined."
A lot of the constant values are scoped in OpenCV. That means, CV_CAP_PROP_POS_MSEC is not defined, but cv::CV_CAP_PROP_POS_MSEC is. You can also obtain the FPS with cv::CAP_PROP_FPS.
Now to your code, I would actually do something that does not require to save and load the image, but rather pass the images to be processed, like this:
#include "opencv2/opencv.hpp"
#include <iostream>
int main(){
cv::VideoCapture cap("D:\\data\\extra\\video200ul.avi");
if (!cap.isOpened())
{
std::cout << "Could not open video" << std::endl;
return -1;
}
cv::Ptr<cv::BackgroundSubtractor> pMOG2 = cv::createBackgroundSubtractorMOG2(20, 16, true);
cv::Mat fg_mask, frame;
int count = 0;
const int fps = 24; // you may set here the fps or get them from the video
std::string name, folder;
// with cap.read you can check already if the video ended
while (cap.read(frame)) {
// Background subtraction
if (count % fps == 0) {
pMOG2->apply(frame, fg_mask, 0.001);
// Save foreground mask
name = "mask" + std::to_string(count) + ".png";
bool result = cv::imwrite("D:\\data\\extra\\" + name, frame);
imageAnalysis(frame, count);
}
// at the end of the loop so that the first image is used
++count;
}
cv::waitKey(0);
return 0;
}
And the imageAnalysis function is defined as:
// You can pass cv::Mat as value, it is almost like a smart pointer
void imageAnalysis(cv::Mat frame, int count)
{
cv::Mat ori_image = frame.clone();
cv::rectangle(ori_image, Point(215, 98), Point(245, 110), Scalar(0, 255, 255), 1);
// each imshow needs a waitKey to update the window in which it is being shown
cv::imshow("Original Image", ori_image);
cv::waitKey(1);
cv::Scalar sums;
sums = cv::sum(ori_image);
double totalSum = sums[0] + sums[1] + sums[2];
std::ofstream output("D:\\data\\extra\\mask" + std::to_string(count) + ".txt");
if (totalSum <= 0)
{
std::cout << "$$ RGB percentage $$" << std::endl << std::endl;
std::cout << "R: " << 100.0 / 3 << std::endl;
std::cout << "G: " << 100.0 / 3 << std::endl;
std::cout << "B: " << 100.0 / 3 << std::endl << std::endl;
output << "$$ RGB percentage $$" << std::endl << std::endl;
output << "R: " << 100.0 / 3 << std::endl;
output << "G: " << 100.0 / 3 << std::endl;
output << "B: " << 100.0 / 3 << std::endl << std::endl;
}
else {
std::cout << "$$ RGB percentage $$" << std::endl << std::endl;
std::cout << "R: " << sums[2] / totalSum * 100 << std::endl; // red value
std::cout << "G: " << sums[1] / totalSum * 100 << std::endl; // green value
std::cout << "B: " << sums[0] / totalSum * 100 << std::endl << std::endl; // blue value
output << "$$ RGB percentage $$" << std::endl << std::endl;
output << "R: " << sums[2] / totalSum * 100 << std::endl; // red value
output << "G: " << sums[1] / totalSum * 100 << std::endl; // green value
output << "B: " << sums[0] / totalSum * 100 << std::endl << std::endl; // blue value
}
}
Some comments of the code above, I replaced the cap >> frame to cap.read(frame). It is the same functionality, but the later gives a bool result that is false if it could not grab the image, like if the video is over. I change the count add at the end, yo you get the frames 0,23,... this way the first one will be use as well. Finally, you should use the namespaces cv::, std:: etc. This is just best practice, it avoids ambiguities and problems that may arise with certain libraries.
If you do not need the image in disk, but only the analysis, then remove the saving part and pass every frame to the imageAnalysis function, this way you may have more data for your statistics. Also, consider returning the cv:Scalar of sums in the function and then you can do some statistics of the whole second or the whole video.
If you have any question, feel free to ask in the comments.

How to visualize Caffe deep learning process's individual layer output in C++?

I am using Caffe for deep learning. My program is in C++.
Every iteration of forward at net_->Forward(&loss);, we pass through all layers as defined in the prototxt file and how can I visualize each layer's output in C++.
Inside net.cpp file inside Caffe library, this loop iterate to forward layer by layer.
template <typename Dtype>
Dtype Net<Dtype>::ForwardFromTo(int start, int end) {
CHECK_GE(start, 0);
CHECK_LT(end, layers_.size());
Dtype loss = 0;
for (int i = start; i <= end; ++i) {
//cout << "Forwarding " << layer_names_[i] << endl;
Dtype layer_loss = layers_[i]->Forward(bottom_vecs_[i], top_vecs_[i]);
loss += layer_loss;
if (debug_info_) { ForwardDebugInfo(i); }
}
return loss;
}
top_vecs_[i] is output of each layer and how can I visualize it?
According to Shai's suggestion, what I did is as follow inside ForwardDebugInfo().
for (int top_id = 0; top_id < top_vecs_[layer_id].size(); ++top_id) {
Blob<Dtype>& blob = *top_vecs_[layer_id][top_id];
const string& blob_name = blob_names_[top_id_vecs_[layer_id][top_id]];
string name = blob_name;
for (int i = 0; i < name.length(); ++i) {
if (name[i] == '/')
name[i] = '_';
}
string foldname = "images/"+name;
if (stat(foldname.c_str(), &st) == -1) {
mkdir(foldname.c_str(), 0700);
}
//cout<<"blob_name " << blob_name << " layer_id is " << layer_id << " blob.num() " << blob.num() << " blob.channels() " << blob.channels() << " blob.height() " << blob.height() << " blob.width() " << blob.width() << endl;
///////Plotting output of individual layer
if(blob.height()>1 && blob.width()>1){
cv::Size ss(blob.width(), blob.height());
Dtype* data = blob.mutable_cpu_data();
for(int k=0; k < blob.channels(); k++)
{
cv::Mat channel(ss, CV_32FC1, data);
stringstream s;
s << k;
cv::imwrite(foldname+"/"+s.str()+".jpg",channel*255.0);
channel.release();
data += ss.area();
}
}
// mainImg.release();
/////////////////////////////////////////
const Dtype data_abs_val_mean = blob.asum_data() / blob.count();
LOG_IF(INFO, Caffe::root_solver())
<< " [Forward] "
<< "Layer " << layer_names_[layer_id]
<< ", top blob " << blob_name
<< " data: " << data_abs_val_mean;
}

segmentation fault: 11, extracting data in vector

I'm trying to write a program with opencv and C++. I have an image and I am trying to get the saturation value of determined pixel which is in the (x, y) point. I use the next sentence to do it:
saturation_level = hsv_chanels[1].at<uchar>(x, y);
The thing is that the program builds OK, but when I try to run, it sometimes works fine and sometimes terminates with this error:
Segmentation fault: 11
Do someone know why this error is appearing? I read that this error appears because of the my computer memory but I don't know why it only appears sometimes.
EDIT:
This is the function I call to find the homography:
Mat ObtenHomografiaSuelo (vector <KeyPoint> keypoints1, vector <KeyPoint> keypoints2, Mat imagen1, Mat imagen2){
//*****************************************************************************
//Find homography mat
//*****************************************************************************
vector < Point2f > image_points[2];
int cont = 0;
vector<Mat> chanels_hsv1; //[0]->H, [1]->S, [2]->V
split( image1, chanels_hsv1 );
vector<Mat> chanels_hsv2;
split( image2, chanels_hsv2 );
for(vector<KeyPoint>::const_iterator it = keypoints1.begin(); it!= keypoints1.end(); ++it){
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
cout << "1" << endl;
float saturation_level = chanels_hsv1[1].at<uchar>(x, y);
cout << "2" << endl;
double max_level = 70.0;
cout << "3" << endl;
if ((y < camSize.height/4) && (saturatio_level < max_level) ){
cout << "1:" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[0].push_back(Point2f(x,y));
cout << "done" << endl;
cont ++;
}
}
cont = 0;
for (vector<KeyPoint>::const_iterator it = keypoints2.begin(); it!=keypoints2.end(); ++it) {
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
float saturation_level = chanels_hsv2[1].at<uchar>(x, y);
double max_level = 70.0;
if ((y < (camSize.height)/4) && (saturation_level < max_level)){
cout << "2" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[1].push_back(Point2f(x,y));
cont ++;
}
}
cout << "We are obtain: " << cont << " points to do the homography" << endl;
waitKey();
Mat H;
H = Mat::zeros(4, 4, CV_64F);
if (cont < 4) {
cout << "Few points to do the homography" << endl;
}
else{
if (image_points[0].size() > image_points[1].size()){
image_points[0].resize(image_points[1].size());
}
else if (image_points[1].size() > image_points[0].size()){
image_points[1].resize(image_points[0].size());
}
H = findHomography (image_points[0], image_points[1], CV_RANSAC, 3);
cout << "done_matrix" << endl;
}
return H;
}
Before to call the function I detect keypoints using Harris or any other detector and the image I passed to the function is a HSV_image converted by cvtColor function.
The error appears in the line that I mentioned before because in the terminal I can se:
1
Segmentation Fault: 11
I've just finished to correct the error, I think it was because I wasn't using efficiently my function. I was using two 'for' staments to cross my two vectors of keypoints detected and the errors sometimes appears at first and others at second one. I don't really know why was the error, I just change my code to do the same think more efficiently and finally it works.
I just changed this lines:
for(vector<KeyPoint>::const_iterator it = keypoints1.begin(); it!= keypoints1.end(); ++it){
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
cout << "1" << endl;
float saturation_level = chanels_hsv1[1].at<uchar>(x, y);
cout << "2" << endl;
double max_level = 70.0;
cout << "3" << endl;
if ((y < camSize.height/4) && (saturatio_level < max_level) ){
cout << "1:" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[0].push_back(Point2f(x,y));
cout << "done" << endl;
cont ++;
}
cont = 0;
for (vector<KeyPoint>::const_iterator it = keypoints2.begin(); it!=keypoints2.end(); ++it) {
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
float saturation_level = chanels_hsv2[1].at<uchar>(x, y);
double max_level = 70.0;
if ((y < (camSize.height)/4) && (saturation_level < max_level)){
cout << "2" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[1].push_back(Point2f(x,y));
cont ++;
}
}
by this ones:
for (int i = 0; i < good_matches.size(); i++) {
int idx1=good_matches[i].queryIdx;
int idx2=good_matches[i].trainIdx;
if (((keypoints[0][idx1].pt.y < (camSize.height/4)) && (canales_hsv1[1].at<uchar>(keypoints[0][idx1].pt.x, keypoints[0][idx1].pt.y) < nivel_maximo)) || ((keypoints[1][idx2].pt.y < (camSize.height/4)) && (canales_hsv2[1].at<uchar>(keypoints[1][idx1].pt.x, keypoints[1][idx2].pt.y) < nivel_maximo)) ) {
cout << "entro" << endl;
matched_points[0].push_back(keypoints[0][idx1].pt);
matched_points[1].push_back(keypoints[1][idx2].pt);
contador ++;
}
}
Currently I only cross the matched keypoints instead of all the keypoints, it requires less computers operations and now it works OK.

Head Pose Estimation on Random Forest in G Fanelli's paper

I have been working on head pose estimation on depth data. And I have read G Fanelli's paper-"Real Time Head Pose Estimation from Consumer Depth Cameras" "Real Time Head Pose Estimation with Random Regression Forests". I test the data and the code Fanelli published on the website(http://www.vision.ee.ethz.ch/~gfanelli/head_pose/head_forest.html). However when I run the code, there is a problem. The error information is "usage: ./head_pose_estimation config_file depth_image". I think it is about file reading but I don't how to fix it.
and the code is like this:
int main(int argc, char* argv[])
{
if( argc != 3 )
{
cout << "usage: ./head_pose_estimation config_file depth_image" << endl;
exit(-1);
}
loadConfig(argv[1]);
CRForestEstimator estimator;
if( !estimator.loadForest(g_treepath.c_str(), g_ntrees) ){
cerr << "could not read forest!" << endl;
exit(-1);
}
string depth_fname(argv[2]);
//read calibration file (should be in the same directory as the depth image!)
string cal_filename = depth_fname.substr(0,depth_fname.find_last_of("/")+1);
cal_filename += "depth.cal";
ifstream is(cal_filename.c_str());
if (!is){
cerr << "depth.cal file not found in the same folder as the depth image! " << endl;
return -1;
}
//read intrinsics only
float depth_intrinsic[9]; for(int i =0; i<9; ++i) is >> depth_intrinsic[i];
is.close();
Mat depthImg;
//read depth image (compressed!)
if (!loadDepthImageCompressed( depthImg, depth_fname.c_str() ))
return -1;
Mat img3D;
img3D.create( depthImg.rows, depthImg.cols, CV_32FC3 );
//get 3D from depth
for(int y = 0; y < img3D.rows; y++)
{
Vec3f* img3Di = img3D.ptr<Vec3f>(y);
const int16_t* depthImgi = depthImg.ptr<int16_t>(y);
for(int x = 0; x < img3D.cols; x++){
float d = (float)depthImgi[x];
if ( d < g_max_z && d > 0 ){
img3Di[x][0] = d * (float(x) - depth_intrinsic[2])/depth_intrinsic[0];
img3Di[x][1] = d * (float(y) - depth_intrinsic[5])/depth_intrinsic[4];
img3Di[x][2] = d;
}
else{
img3Di[x] = 0;
}
}
}
g_means.clear();
g_votes.clear();
g_clusters.clear();
string pose_filename(depth_fname.substr(0,depth_fname.find_last_of('_')));
pose_filename += "_pose.bin";
cv::Vec<float,POSE_SIZE> gt;
bool have_gt = false;
//try to read in the ground truth from a binary file
FILE* pFile = fopen(pose_filename.c_str(), "rb");
if(pFile){
have_gt = true;
have_gt &= ( fread( &gt[0], sizeof(float),POSE_SIZE, pFile) == POSE_SIZE );
fclose(pFile);
}
//do the actual estimate
estimator.estimate( img3D,
g_means,
g_clusters,
g_votes,
g_stride,
g_maxv,
g_prob_th,
g_larger_radius_ratio,
g_smaller_radius_ratio,
false,
g_th
);
cout << "Heads found : " << g_means.size() << endl;
//assuming there's only one head in the image!
if(g_means.size()>0){
cout << "Estimated: " << g_means[0][0] << " " << g_means[0][1] << " " << g_means[0][2] << " " << g_means[0][3] << " " << g_means[0][4] << " " << g_means[0][5] <<endl;
float pt2d_est[2];
float pt2d_gt[2];
if(have_gt){
cout << "Ground T.: " << gt[0] << " " << gt[1] << " " << gt[2] << " " << gt[3] << " " << gt[4] << " " << gt[5] <<endl;
cv::Vec<float,POSE_SIZE> err = (gt-g_means[0]);
//multiply(err,err,err);
for(int n=0;n<POSE_SIZE;++n)
err[n] = err[n]*err[n];
float h_err = sqrt(err[0]+err[1]+err[2]);
float a_err = sqrt(err[3]+err[4]+err[5]);
cout << "Head error : " << h_err << " mm " << endl;
cout << "Angle error : " << a_err <<" degrees " << endl;
pt2d_gt[0] = depth_intrinsic[0]*gt[0]/gt[2] + depth_intrinsic[2];
pt2d_gt[1] = depth_intrinsic[4]*gt[1]/gt[2] + depth_intrinsic[5];
}
pt2d_est[0] = depth_intrinsic[0]*g_means[0][0]/g_means[0][2] + depth_intrinsic[2];
pt2d_est[1] = depth_intrinsic[4]*g_means[0][1]/g_means[0][2] + depth_intrinsic[5];
}
return 0;
}
can anyone could tell me how to fix the problem?Thanks so much!
You should always read the readme.txt (here attached in head_pose_estimation.tgz) before testing an application:
To run the example code, type ./head_pose_estimation config.txt
data/frame_XXXX_depth.bin. The config.txt file contains all parameters
needed for the head pose estimation, e.g., the path to the forest, the
stride, and z threshold used to segment the person from the
background.