Possibly Wrong Equations of planes of Convex Hull using CGAL - computational-geometry

I am new to Computational Geometry. This may be a naive question. I have used CGAL to find convex hull of a set of points. Then I extract the planes for convex hull using the example code given on the CGAL website here. The program is given below.
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/GMP/Gmpq_type.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/convex_hull_3.h>
#include <CGAL/Side_of_triangle_mesh.h>
#include <CGAL/number_utils.h>
#include <iomanip>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron_3;
typedef Kernel::Point_3 Point_3;
typedef Kernel::Plane_3 Plane_3;
typedef Kernel::Vector_3 Vector_3;
typedef CGAL::Side_of_triangle_mesh<Polyhedron_3, Kernel> Point_inside;
struct Plane_equation {
template <class Facet>
typename Facet::Plane_3 operator()( Facet& f) {
typename Facet::Halfedge_handle h = f.halfedge();
typedef typename Facet::Plane_3 Plane;
return Plane( h->vertex()->point(),
h->next()->vertex()->point(),
h->next()->next()->vertex()->point());
}
};
Point_3 create_point(std::string x, std::string y, std::string z) {
Point_3 p;
std::istringstream input(x + " " + y + " " + z);
input >> p;
return p;
}
int main() {
std::vector<Point_3> points;
points.push_back(create_point("-780692485006853753617237/10240000000000000000000000000",
"-1563546083667768699030143/2500000000000000000000000",
"0"));
points.push_back(create_point("379213264894343110801237/10240000000000000000000000000",
"-1563546083667768699030143/2500000000000000000000000",
"0"));
points.push_back(create_point("-780692485006853753617237/10240000000000000000000000000",
"0",
"0"));
points.push_back(create_point("379213264894343110801237/10240000000000000000000000000",
"-379213264894343110801237/10240000000000000000000000000",
"0"));
points.push_back(create_point("-780692485006853753617237/10240000000000000000000000000",
"3223865085330535926726143/2500000000000000000000000",
"-780692485006853753617237/10240000000000000000000000000"));
points.push_back(create_point("379213264894343110801237/10240000000000000000000000000",
"3223865085330535926726143/2500000000000000000000000",
"379213264894343110801237/10240000000000000000000000000"));
points.push_back(create_point("379213264894343110801237/10240000000000000000000000000",
"0",
"379213264894343110801237/10240000000000000000000000000"));
points.push_back(create_point("-780692485006853753617237/10240000000000000000000000000",
"780692485006853753617237/10240000000000000000000000000",
"-780692485006853753617237/10240000000000000000000000000"));
points.push_back(create_point("0", "0", "0"));
Polyhedron_3 poly;
CGAL::convex_hull_3(points.begin(), points.end(), poly);
// CGAL::draw(poly);
std::transform(poly.facets_begin(), poly.facets_end(), poly.planes_begin(), Plane_equation());
CGAL::set_pretty_mode(std::cout);
std::copy(poly.planes_begin(), poly.planes_end(),
std::ostream_iterator<Plane_3>(std::cout, "\n"));
Point_inside inside_tester(poly);
CGAL::Bounded_side res = inside_tester(Point_3(0, 0, 0));
if (res == CGAL::ON_BOUNDED_SIDE) {
std::cout << "Origin is inside" << "\n";
} else if (res == CGAL::ON_BOUNDARY) {
std::cout << "Origin is on the boundary" << "\n";
} else {
std::cout << "Origin is outside the polyhedron" << "\n";
}
for (auto it = poly.planes_begin(); it != poly.planes_end(); ++it) {
std::cout << "A = " << it->a().exact() << "\n";
std::cout << "B = " << it->b().exact() << "\n";
std::cout << "C = " << it->c().exact() << "\n";
std::cout << "D = " << it->d().exact() << "\n";
std::cout << "\n";
}
return EXIT_SUCCESS;
}
After generating convex hull using convex_hull_3, I try to extract the plane equations for all the planes. Below is the output for the program
Plane_3(0, -4.19475e-09, 7.08424e-05, -2.62348e-09)
Plane_3(-4.76816e-05, 0, 0, -3.63522e-09)
Plane_3(4.76788e-05, 0, -7.08382e-05, -1.76567e-09)
Plane_3(-9.83085e-05, 0, 0, -7.49499e-09)
Plane_3(-0.00014607, 8.6358e-09, 0.00014607, -1.11363e-08)
Plane_3(9.83085e-05, 0, -0.000146061, -3.64062e-09)
Plane_3(0.000146074, 4.19475e-09, -0.000146074, -5.40933e-09)
Plane_3(0, -8.6358e-09, -7.08511e-05, -5.40099e-09)
Plane_3(-4.77552e-05, 0, 0.00014607, -3.64083e-09)
Plane_3(-2.31608e-05, 0, 7.08424e-05, -1.76577e-09)
Plane_3(4.77552e-05, 0, 0, -1.7685e-09)
Plane_3(2.31595e-05, 0, 0, -8.57654e-10)
Origin is inside
A = 0
B = -219925823194877128532786493609493825335102426169/52428800000000000000000000000000000000000000000000000000
C = 906783046340871373991245871626108775814746030891/12800000000000000000000000000000000000000000000000000
D = -343864159553760260821702206832186399183132849909762204558692676563012167/131072000000000000000000000000000000000000000000000000000000000000000000000000000
A = -1220648677481324419677714143344481488159947374891/25600000000000000000000000000000000000000000000000000
B = 0
C = 0
D = -952951249343224727578040741115129097199790308301319818242882753758596167/262144000000000000000000000000000000000000000000000000000000000000000000000000000
A = 4999480934017386895980017109227629957533970363431367/104857600000000000000000000000000000000000000000000000000
B = 0
C = -3713963431989014270739610303686932051911864640103367/52428800000000000000000000000000000000000000000000000000
D = -1895869487765753248495994462519358098874827535092392449815572846416028200979/1073741824000000000000000000000000000000000000000000000000000000000000000000000000000
A = -10308396833918147444194565967124294714798768363431367/104857600000000000000000000000000000000000000000000000000
B = 0
C = 0
D = -8047687940708342026893035469747920357861814098710951530122415210209637672979/1073741824000000000000000000000000000000000000000000000000000000000000000000000000000
A = -1869689824690300646434385556309825774908173982891/12800000000000000000000000000000000000000000000000000
B = 452764851132051796393052935016376879217993818169/52428800000000000000000000000000000000000000000000000000
C = 1869689824690300646434385556309825774908173982891/12800000000000000000000000000000000000000000000000000
D = -1459652795429499560461049209852394023543048968469784428121757724600692167/131072000000000000000000000000000000000000000000000000000000000000000000000000000
A = 10308396833918147444194565967124294714798768363431367/104857600000000000000000000000000000000000000000000000000
B = 0
C = -7657796757080339395998850185710029997144662640103367/52428800000000000000000000000000000000000000000000000000
D = -3909080819216610292966257636154114768379010997867208966773927801542028200979/1073741824000000000000000000000000000000000000000000000000000000000000000000000000000
A = 1531693889550933264984755205027731173569843147269541/10485760000000000000000000000000000000000000000000000000
B = 219925823194877128532786493609493825335102426169/52428800000000000000000000000000000000000000000000000000
C = -1531693889550933264984755205027731173569843147269541/10485760000000000000000000000000000000000000000000000000
D = -709011182760540911322636241675226035790615443402528424913924328539636167/131072000000000000000000000000000000000000000000000000000000000000000000000000000
A = 0
B = -452764851132051796393052935016376879217993818169/52428800000000000000000000000000000000000000000000000000
C = -742927224532668239932907228623111584523283547269541/10485760000000000000000000000000000000000000000000000000
D = -707918709809939897610498041142184898705751664465632699646023679792068167/131072000000000000000000000000000000000000000000000000000000000000000000000000000
A = -1222532404587072576861092389210725463247004638891/25600000000000000000000000000000000000000000000000000
B = 0
C = 1869689824690300646434385556309825774908173982891/12800000000000000000000000000000000000000000000000000
D = -954421860938486024795167813392498809224920480657508534678004510218164167/262144000000000000000000000000000000000000000000000000000000000000000000000000000
A = -592917415200418328304777599907736063469544686891/25600000000000000000000000000000000000000000000000000
B = 0
C = 906783046340871373991245871626108775814746030891/12800000000000000000000000000000000000000000000000000
D = -462886170276655067642955341169240700211713020629945581049164605825540167/262144000000000000000000000000000000000000000000000000000000000000000000000000000
A = 1222532404587072576861092389210725463247004638891/25600000000000000000000000000000000000000000000000000
B = 0
C = 0
D = -463600504582595797850104669957953262356310406147548315149844146861108167/262144000000000000000000000000000000000000000000000000000000000000000000000000000
A = 2428445929960641645499203498146234146289758916775367/104857600000000000000000000000000000000000000000000000000
B = 0
C = 0
D = -920898909719754197337687026347401189092620563028663434317768459371714728979/1073741824000000000000000000000000000000000000000000000000000000000000000000000000000
You can notice the line which says that origin is inside the convex hull. Now if the origin is inside the convex hull, then if I check the side of origin relative to a plane by checking 0*a + 0*b + 0*c + d, then for some planes, the output should be positive and for some it should be negative. But in this case, the outputs (essentially the d value) is negative for all planes. What is it that I'm doing wrong here?

Related

Incorrect result with cpp_dec_float division

I'm having a problem with boost cpp_dec_float division producing wrong results.
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
int main()
{
using namespace boost::multiprecision;
using namespace std;
cpp_dec_float_50 a = 15; // exactly 5 * 3
cpp_dec_float_50 b = 3;
cpp_dec_float_50 c = a / b; // should be exactly 5
cpp_dec_float_50 d = 5;
cout << setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10);
cout << "c: " << c << endl;
cout << "d: " << d << endl;
cout << "c == d: " << (c == d ? "true" : "false") << endl;
return 0;
}
This produces
c: 4.999999999999999999999999999999999999999999999999999999999999999999999995
d: 5
c == d: false
I saw this question which discusses it for a fractional result. While some comments there were trying to explain it as an effect of truncation, that was not convincing IMO.
And in my case, all values, including the result, are integers, so if there is a decimal arithmetic performed, no truncation should happen.
Any ideas to make boost produce the correct/expected results?

Error when debugging sample in OPENCV Camera Calibration using OPEN CV. Assertion failed ( count >=0) cornersubpix. Opencv 3.2 with VS15

I am getting an error when using Camera_Calibration.cpp on OpenCv Tutorial (photo). i running it in release mode.
.
I got assertion fail. I debugged this project by command window with in_VID5.xml
in_VID5.xml:
<?xml version="1.0"?>
<opencv_storage>
<Settings>
<!-- Number of inner corners per a item row and column. (square, circle) -->
<BoardSize_Width>7</BoardSize_Width>
<BoardSize_Height>5</BoardSize_Height>
<!-- The size of a square in some user defined metric system (pixel, millimeter)-->
<Square_Size>30</Square_Size>
<!-- The type of input used for camera calibration. One of: CHESSBOARD CIRCLES_GRID ASYMMETRIC_CIRCLES_GRID -->
<Calibrate_Pattern>"CHESSBOARD"</Calibrate_Pattern>
<!-- The input to use for calibration.
To use an input camera -> give the ID of the camera, like "1"
To use an input video -> give the path of the input video, like "/tmp/x.avi"
To use an image list -> give the path to the XML or YAML file containing the list of the images, like "/tmp/circles_list.xml"
-->
<Input>"1"</Input>
<!-- If true (non-zero) we flip the input images around the horizontal axis.-->
<Input_FlipAroundHorizontalAxis>0</Input_FlipAroundHorizontalAxis>
<!-- Time delay between frames in case of camera. -->
<Input_Delay>100</Input_Delay>
<!-- How many frames to use, for calibration. -->
<Calibrate_NrOfFrameToUse>10</Calibrate_NrOfFrameToUse>
<!-- Consider only fy as a free parameter, the ratio fx/fy stays the same as in the input cameraMatrix.
Use or not setting. 0 - False Non-Zero - True-->
<Calibrate_FixAspectRatio> 1 </Calibrate_FixAspectRatio>
<!-- If true (non-zero) tangential distortion coefficients are set to zeros and stay zero.-->
<Calibrate_AssumeZeroTangentialDistortion>1</Calibrate_AssumeZeroTangentialDistortion>
<!-- If true (non-zero) the principal point is not changed during the global optimization.-->
<Calibrate_FixPrincipalPointAtTheCenter> 1 </Calibrate_FixPrincipalPointAtTheCenter>
<!-- The name of the output log file. -->
<Write_outputFileName>"out_camera_data.xml"</Write_outputFileName>
<!-- If true (non-zero) we write to the output file the feature points.-->
<Write_DetectedFeaturePoints>1</Write_DetectedFeaturePoints>
<!-- If true (non-zero) we write to the output file the extrinsic camera parameters.-->
<Write_extrinsicParameters>1</Write_extrinsicParameters>
<!-- If true (non-zero) we show after calibration the undistorted images.-->
<Show_UndistortedImage>1</Show_UndistortedImage>
</Settings>
</opencv_storage>
My code:
#include
#include <sstream>
#include <time.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
void help()
{
cout << "This is a camera calibration sample." << endl
<< "Usage: calibration configurationFile" << endl
<< "Near the sample file you'll find the configuration file, which has detailed help of "
"how to edit it. It may be any OpenCV supported file format XML/YAML." << endl;
}
class Settings
{
public:
Settings() : goodInput(false) {}
enum Pattern { NOT_EXISTING, CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID };
enum InputType { INVALID, CAMERA, VIDEO_FILE, IMAGE_LIST };
void write(FileStorage& fs) const //Write serialization for this class
{
fs << "{" << "BoardSize_Width" << boardSize.width
<< "BoardSize_Height" << boardSize.height
<< "Square_Size" << squareSize
<< "Calibrate_Pattern" << patternToUse
<< "Calibrate_NrOfFrameToUse" << nrFrames
<< "Calibrate_FixAspectRatio" << aspectRatio
<< "Calibrate_AssumeZeroTangentialDistortion" << calibZeroTangentDist
<< "Calibrate_FixPrincipalPointAtTheCenter" << calibFixPrincipalPoint
<< "Write_DetectedFeaturePoints" << bwritePoints
<< "Write_extrinsicParameters" << bwriteExtrinsics
<< "Write_outputFileName" << outputFileName
<< "Show_UndistortedImage" << showUndistorsed
<< "Input_FlipAroundHorizontalAxis" << flipVertical
<< "Input_Delay" << delay
<< "Input" << input
<< "}";
}
void read(const FileNode& node) //Read serialization for this class
{
node["BoardSize_Width"] >> boardSize.width;
node["BoardSize_Height"] >> boardSize.height;
node["Calibrate_Pattern"] >> patternToUse;
node["Square_Size"] >> squareSize;
node["Calibrate_NrOfFrameToUse"] >> nrFrames;
node["Calibrate_FixAspectRatio"] >> aspectRatio;
node["Write_DetectedFeaturePoints"] >> bwritePoints;
node["Write_extrinsicParameters"] >> bwriteExtrinsics;
node["Write_outputFileName"] >> outputFileName;
node["Calibrate_AssumeZeroTangentialDistortion"] >> calibZeroTangentDist;
node["Calibrate_FixPrincipalPointAtTheCenter"] >> calibFixPrincipalPoint;
node["Input_FlipAroundHorizontalAxis"] >> flipVertical;
node["Show_UndistortedImage"] >> showUndistorsed;
node["Input"] >> input;
node["Input_Delay"] >> delay;
interprate();
}
void interprate()
{
goodInput = true;
if (boardSize.width <= 0 || boardSize.height <= 0)
{
cerr << "Invalid Board size: " << boardSize.width << " " << boardSize.height << endl;
goodInput = false;
}
if (squareSize <= 10e-6)
{
cerr << "Invalid square size " << squareSize << endl;
goodInput = false;
}
if (nrFrames <= 0)
{
cerr << "Invalid number of frames " << nrFrames << endl;
goodInput = false;
}
if (input.empty()) // Check for valid input
inputType = INVALID;
else
{
if (input[0] >= '0' && input[0] <= '9')
{
stringstream ss(input);
ss >> cameraID;
inputType = CAMERA;
}
else
{
if (readStringList(input, imageList))
{
inputType = IMAGE_LIST;
nrFrames = (nrFrames < imageList.size()) ? nrFrames : imageList.size();
}
else
inputType = VIDEO_FILE;
}
if (inputType == CAMERA)
inputCapture.open(cameraID);
if (inputType == VIDEO_FILE)
inputCapture.open(input);
if (inputType != IMAGE_LIST && !inputCapture.isOpened())
inputType = INVALID;
}
if (inputType == INVALID)
{
cerr << " Inexistent input: " << input;
goodInput = false;
}
flag = 0;
if (calibFixPrincipalPoint) flag |= CV_CALIB_FIX_PRINCIPAL_POINT;
if (calibZeroTangentDist) flag |= CV_CALIB_ZERO_TANGENT_DIST;
if (aspectRatio) flag |= CV_CALIB_FIX_ASPECT_RATIO;
calibrationPattern = NOT_EXISTING;
if (!patternToUse.compare("CHESSBOARD")) calibrationPattern = CHESSBOARD;
if (!patternToUse.compare("CIRCLES_GRID")) calibrationPattern = CIRCLES_GRID;
if (!patternToUse.compare("ASYMMETRIC_CIRCLES_GRID")) calibrationPattern = ASYMMETRIC_CIRCLES_GRID;
if (calibrationPattern == NOT_EXISTING)
{
cerr << " Inexistent camera calibration mode: " << patternToUse << endl;
goodInput = false;
}
atImageList = 0;
}
Mat nextImage()
{
Mat result;
if (inputCapture.isOpened())
{
Mat view0;
inputCapture >> view0;
view0.copyTo(result);
}
else if (atImageList < (int)imageList.size())
result = imread(imageList[atImageList++], CV_LOAD_IMAGE_COLOR);
return result;
}
static bool readStringList(const string& filename, vector<string>& l)
{
l.clear();
FileStorage fs(filename, FileStorage::READ);
if (!fs.isOpened())
return false;
FileNode n = fs.getFirstTopLevelNode();
if (n.type() != FileNode::SEQ)
return false;
FileNodeIterator it = n.begin(), it_end = n.end();
for (; it != it_end; ++it)
l.push_back((string)*it);
return true;
}
public:
Size boardSize; // The size of the board -> Number of items by width and height
Pattern calibrationPattern;// One of the Chessboard, circles, or asymmetric circle pattern
float squareSize; // The size of a square in your defined unit (point, millimeter,etc).
int nrFrames; // The number of frames to use from the input for calibration
float aspectRatio; // The aspect ratio
int delay; // In case of a video input
bool bwritePoints; // Write detected feature points
bool bwriteExtrinsics; // Write extrinsic parameters
bool calibZeroTangentDist; // Assume zero tangential distortion
bool calibFixPrincipalPoint;// Fix the principal point at the center
bool flipVertical; // Flip the captured images around the horizontal axis
string outputFileName; // The name of the file where to write
bool showUndistorsed; // Show undistorted images after calibration
string input; // The input ->
int cameraID;
vector<string> imageList;
int atImageList;
VideoCapture inputCapture;
InputType inputType;
bool goodInput;
int flag;
private:
string patternToUse;
};
void write(FileStorage& fs, const std::string&, const Settings& x)
{
x.write(fs);
}
void read(const FileNode& node, Settings& x, const Settings& default_value = Settings())
{
if (node.empty())
x = default_value;
else
x.read(node);
}
enum { DETECTION = 0, CAPTURING = 1, CALIBRATED = 2 };
bool runCalibrationAndSave(Settings& s, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs,
vector<vector<Point2f> > imagePoints);
int main(int argc, char* argv[])
{
help();
Settings s;
const string inputSettingsFile = argc > 1 ? argv[1] : "in_VID5.xml";
FileStorage fs(inputSettingsFile, FileStorage::READ); // Read the settings
if (!fs.isOpened())
{
cout << "Could not open the configuration file: \"" << inputSettingsFile << "\"" << endl;
return -1;
}
fs["Settings"] >> s;
fs.release(); // close Settings file
if (!s.goodInput)
{
cout << "Invalid input detected. Application stopping. " << endl;
return -1;
}
vector<vector<Point2f> > imagePoints;
Mat cameraMatrix, distCoeffs;
Size imageSize;
int mode = s.inputType == Settings::IMAGE_LIST ? CAPTURING : DETECTION;
clock_t prevTimestamp = 0;
const Scalar RED(0, 0, 255), GREEN(0, 255, 0);
const char ESC_KEY = 27;
for (int i = 0;; ++i)
{
Mat view;
bool blinkOutput = false;
view = s.nextImage();
//----- If no more image, or got enough, then stop calibration and show result -------------
if (mode == CAPTURING && imagePoints.size() >= (unsigned)s.nrFrames)
{
if (runCalibrationAndSave(s, imageSize, cameraMatrix, distCoeffs, imagePoints))
mode = CALIBRATED;
else
mode = DETECTION;
}
if (view.empty()) // If no more images then run calibration, save and stop loop.
{
if (imagePoints.size() > 0)
runCalibrationAndSave(s, imageSize, cameraMatrix, distCoeffs, imagePoints);
break;
}
imageSize = view.size(); // Format input image.
if (s.flipVertical) flip(view, view, 0);
vector<Point2f> pointBuf;
bool found;
switch (s.calibrationPattern) // Find feature points on the input format
{
case Settings::CHESSBOARD:
found = findChessboardCorners(view, s.boardSize, pointBuf,
CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK | CV_CALIB_CB_NORMALIZE_IMAGE);
break;
case Settings::CIRCLES_GRID:
found = findCirclesGrid(view, s.boardSize, pointBuf);
break;
case Settings::ASYMMETRIC_CIRCLES_GRID:
found = findCirclesGrid(view, s.boardSize, pointBuf, CALIB_CB_ASYMMETRIC_GRID);
break;
}
if (found) // If done with success,
{
// improve the found corners' coordinate accuracy for chessboard
if (s.calibrationPattern == Settings::CHESSBOARD)
{
Mat viewGray;
cvtColor(view, viewGray, CV_BGR2GRAY);
cornerSubPix(viewGray, pointBuf, Size(11, 11),
Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
}
if (mode == CAPTURING && // For camera only take new samples after delay time
(!s.inputCapture.isOpened() || clock() - prevTimestamp > s.delay*1e-3*CLOCKS_PER_SEC))
{
imagePoints.push_back(pointBuf);
prevTimestamp = clock();
blinkOutput = s.inputCapture.isOpened();
}
// Draw the corners.
drawChessboardCorners(view, s.boardSize, Mat(pointBuf), found);
}
//----------------------------- Output Text ------------------------------------------------
string msg = (mode == CAPTURING) ? "100/100" :
mode == CALIBRATED ? "Calibrated" : "Press 'g' to start";
int baseLine = 0;
Size textSize = getTextSize(msg, 1, 1, 1, &baseLine);
Point textOrigin(view.cols - 2 * textSize.width - 10, view.rows - 2 * baseLine - 10);
if (mode == CAPTURING)
{
if (s.showUndistorsed)
msg = format("%d/%d Undist", (int)imagePoints.size(), s.nrFrames);
else
msg = format("%d/%d", (int)imagePoints.size(), s.nrFrames);
}
putText(view, msg, textOrigin, 1, 1, mode == CALIBRATED ? GREEN : RED);
if (blinkOutput)
bitwise_not(view, view);
//------------------------- Video capture output undistorted ------------------------------
if (mode == CALIBRATED && s.showUndistorsed)
{
Mat temp = view.clone();
undistort(temp, view, cameraMatrix, distCoeffs);
}
//------------------------------ Show image and check for input commands -------------------
imshow("Image View", view);
char key = waitKey(s.inputCapture.isOpened() ? 50 : s.delay);
if (key == ESC_KEY)
break;
if (key == 'u' && mode == CALIBRATED)
s.showUndistorsed = !s.showUndistorsed;
if (s.inputCapture.isOpened() && key == 'g')
{
mode = CAPTURING;
imagePoints.clear();
}
}
// -----------------------Show the undistorted image for the image list ------------------------
if (s.inputType == Settings::IMAGE_LIST && s.showUndistorsed)
{
Mat view, rview, map1, map2;
initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(),
getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0),
imageSize, CV_16SC2, map1, map2);
for (int i = 0; i < (int)s.imageList.size(); i++)
{
view = imread(s.imageList[i], 1);
if (view.empty())
continue;
remap(view, rview, map1, map2, INTER_LINEAR);
imshow("Image View", rview);
char c = waitKey();
if (c == ESC_KEY || c == 'q' || c == 'Q')
break;
}
}
return 0;
}
double computeReprojectionErrors(const vector<vector<Point3f> >& objectPoints,
const vector<vector<Point2f> >& imagePoints,
const vector<Mat>& rvecs, const vector<Mat>& tvecs,
const Mat& cameraMatrix, const Mat& distCoeffs,
vector<float>& perViewErrors)
{
vector<Point2f> imagePoints2;
int i, totalPoints = 0;
double totalErr = 0, err;
perViewErrors.resize(objectPoints.size());
for (i = 0; i < (int)objectPoints.size(); ++i)
{
projectPoints(Mat(objectPoints[i]), rvecs[i], tvecs[i], cameraMatrix,
distCoeffs, imagePoints2);
err = norm(Mat(imagePoints[i]), Mat(imagePoints2), CV_L2);
int n = (int)objectPoints[i].size();
perViewErrors[i] = (float)std::sqrt(err*err / n);
totalErr += err*err;
totalPoints += n;
}
return std::sqrt(totalErr / totalPoints);
}
void calcBoardCornerPositions(Size boardSize, float squareSize, vector<Point3f>& corners,
Settings::Pattern patternType /*= Settings::CHESSBOARD*/)
{
corners.clear();
switch (patternType)
{
case Settings::CHESSBOARD:
case Settings::CIRCLES_GRID:
for (int i = 0; i < boardSize.height; ++i)
for (int j = 0; j < boardSize.width; ++j)
corners.push_back(Point3f(float(j*squareSize), float(i*squareSize), 0));
break;
case Settings::ASYMMETRIC_CIRCLES_GRID:
for (int i = 0; i < boardSize.height; i++)
for (int j = 0; j < boardSize.width; j++)
corners.push_back(Point3f(float((2 * j + i % 2)*squareSize), float(i*squareSize), 0));
break;
}
}
bool runCalibration(Settings& s, Size& imageSize, Mat& cameraMatrix, Mat& distCoeffs,
vector<vector<Point2f> > imagePoints, vector<Mat>& rvecs, vector<Mat>& tvecs,
vector<float>& reprojErrs, double& totalAvgErr)
{
cameraMatrix = Mat::eye(3, 3, CV_64F);
if (s.flag & CV_CALIB_FIX_ASPECT_RATIO)
cameraMatrix.at<double>(0, 0) = 1.0;
distCoeffs = Mat::zeros(8, 1, CV_64F);
vector<vector<Point3f> > objectPoints(1);
calcBoardCornerPositions(s.boardSize, s.squareSize, objectPoints[0], s.calibrationPattern);
objectPoints.resize(imagePoints.size(), objectPoints[0]);
//Find intrinsic and extrinsic camera parameters
double rms = calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix,
distCoeffs, rvecs, tvecs, s.flag | CV_CALIB_FIX_K4 | CV_CALIB_FIX_K5);
cout << "Re-projection error reported by calibrateCamera: " << rms << endl;
bool ok = checkRange(cameraMatrix) && checkRange(distCoeffs);
totalAvgErr = computeReprojectionErrors(objectPoints, imagePoints,
rvecs, tvecs, cameraMatrix, distCoeffs, reprojErrs);
return ok;
}
// Print camera parameters to the output file
void saveCameraParams(Settings& s, Size& imageSize, Mat& cameraMatrix, Mat& distCoeffs,
const vector<Mat>& rvecs, const vector<Mat>& tvecs,
const vector<float>& reprojErrs, const vector<vector<Point2f> >& imagePoints,
double totalAvgErr)
{
FileStorage fs(s.outputFileName, FileStorage::WRITE);
time_t t;
time(&t);
struct tm *t2 = localtime(&t);
char buf[1024];
strftime(buf, sizeof(buf) - 1, "%c", t2);
fs << "calibration_Time" << buf;
if (!rvecs.empty() || !reprojErrs.empty())
fs << "nrOfFrames" << (int)std::max(rvecs.size(), reprojErrs.size());
fs << "image_Width" << imageSize.width;
fs << "image_Height" << imageSize.height;
fs << "board_Width" << s.boardSize.width;
fs << "board_Height" << s.boardSize.height;
fs << "square_Size" << s.squareSize;
if (s.flag & CV_CALIB_FIX_ASPECT_RATIO)
fs << "FixAspectRatio" << s.aspectRatio;
if (s.flag)
{
sprintf(buf, "flags: %s%s%s%s",
s.flag & CV_CALIB_USE_INTRINSIC_GUESS ? " +use_intrinsic_guess" : "",
s.flag & CV_CALIB_FIX_ASPECT_RATIO ? " +fix_aspectRatio" : "",
s.flag & CV_CALIB_FIX_PRINCIPAL_POINT ? " +fix_principal_point" : "",
s.flag & CV_CALIB_ZERO_TANGENT_DIST ? " +zero_tangent_dist" : "");
cvWriteComment(*fs, buf, 0);
}
fs << "flagValue" << s.flag;
fs << "Camera_Matrix" << cameraMatrix;
fs << "Distortion_Coefficients" << distCoeffs;
fs << "Avg_Reprojection_Error" << totalAvgErr;
if (!reprojErrs.empty())
fs << "Per_View_Reprojection_Errors" << Mat(reprojErrs);
if (!rvecs.empty() && !tvecs.empty())
{
CV_Assert(rvecs[0].type() == tvecs[0].type());
Mat bigmat((int)rvecs.size(), 6, rvecs[0].type());
for (int i = 0; i < (int)rvecs.size(); i++)
{
Mat r = bigmat(Range(i, i + 1), Range(0, 3));
Mat t = bigmat(Range(i, i + 1), Range(3, 6));
CV_Assert(rvecs[i].rows == 3 && rvecs[i].cols == 1);
CV_Assert(tvecs[i].rows == 3 && tvecs[i].cols == 1);
//*.t() is MatExpr (not Mat) so we can use assignment operator
r = rvecs[i].t();
t = tvecs[i].t();
}
cvWriteComment(*fs, "a set of 6-tuples (rotation vector + translation vector) for each view", 0);
fs << "Extrinsic_Parameters" << bigmat;
}
if (!imagePoints.empty())
{
Mat imagePtMat((int)imagePoints.size(), imagePoints[0].size(), CV_32FC2);
for (int i = 0; i < (int)imagePoints.size(); i++)
{
Mat r = imagePtMat.row(i).reshape(2, imagePtMat.cols);
Mat imgpti(imagePoints[i]);
imgpti.copyTo(r);
}
fs << "Image_points" << imagePtMat;
}
}
bool runCalibrationAndSave(Settings& s, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector<vector<Point2f> > imagePoints)
{
vector<Mat> rvecs, tvecs;
vector<float> reprojErrs;
double totalAvgErr = 0;
bool ok = runCalibration(s, imageSize, cameraMatrix, distCoeffs, imagePoints, rvecs, tvecs,
reprojErrs, totalAvgErr);
cout << (ok ? "Calibration succeeded" : "Calibration failed")
<< ". avg re projection error = " << totalAvgErr;
if (ok)
saveCameraParams(s, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, reprojErrs,
imagePoints, totalAvgErr);
return ok;
}

Getting “./a.out” terminated by signal SIGSEGV (Address boundary error)

I'm writing a program that splits any two numbers. The problem is whenever I run the program I get an error that says:
“./a.out” terminated by signal SIGSEGV (Address boundary error)
And that error occurs at the lines:
a = std::stoi(temp_vec.front());
b = std::stoi(temp_vec.back());
and
c = std::stoi(temp_vec.front());
d = std::stoi(temp_vec.back());
Here's my program:
#include <iostream>
#include <string>
#include <vector>
void split_number(std::vector<std::string> vect, int x);
int main()
{
int x = 0, y = 0, a = 0, b = 0, c = 0, d = 0;
std::vector<std::string> temp_vec;
std::cout << "Enter x: ";
std::cin >> x;
std::cout << "Enter y: ";
std::cin >> y;
split_number(temp_vec, x);
a = std::stoi(temp_vec.front());
b = std::stoi(temp_vec.back());
split_number(temp_vec, y);
c = std::stoi(temp_vec.front());
d = std::stoi(temp_vec.back());
return 0;
}
void split_number(std::vector<std::string> vect, int x)
{
vect.clear();
//1. convert x to string
std::string temp_str = std::to_string(x);
//2. calculate length
std::size_t len = temp_str.length();
std::size_t delm = 0;
if(len % 2 == 0) {
delm = len / 2;
} else {
delm = (len + 1) / 2;
}
//3. populate vector
vect.push_back(temp_str.substr(0, delm));
vect.push_back(temp_str.substr(delm + 1));
}
Any help would be appreciated.
You get the segmentation fault because your vector is empty. Your vector is empty because you pass a copy of your initial vector to split_number(). The copy is passed because the signature of split_number() says it requires a copy. Change it to:
void split_number(std::vector<std::string> & vect, int x)
The ampersand makes the vect parameter a reference parameter, and modifications will show in the calling code.

Boost Mem_fn and accessing member function of derived class

I made a simple example to test boost bind's interaction with derived classes.
I created two subclasses with different getarea functions. I expected
g1 = boost::bind(boost::mem_fn(&Shape::getarea), Rec)
to print the area of Rectangle(10,20) but instead it printed '1'. I get the same when I instead write Rectangle::getarea. It prints the same even when I input other functions eg. member of Rectangle
double sum(double h,double w){return h+w; }
and use
g1 = boost::bind(boost::mem_fn(&Rectangle::sum), Rec,2,3)
Question 1: Why does it return '1'?Is that a default response for error?
My second problem is to do the same of printing g2 but now Rec is replaced by **iter, i.e. an object of some derived class type from a list of objects. Since getarea is a virtual fcn, once I get the above working it should be fine to just write:
g2= boost::bind(boost::mem_fn(& Shape::getarea , &(**iter));
Question 2: However, I was wondering if there is a way to return the classtype of **iter eg. classof(**iter) and then put it in g2 i.e.
g2= boost::bind(boost::mem_fn(& classof(**iter)::getarea , &(**iter));
When I ran g2 by writing Shape::getarea, I got '1' again for all iter.
#include <memory>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <boost/bind.hpp>
using namespace std;
class Shape {
public:
Shape(double h, double w) :height(h), width(w) {};
virtual double getarea() = 0;
double height;
double width; };
class Rectangle: public Shape {
public:
Rectangle(double h, double w): Shape(h,w) {};
double getarea() override { return height*width; } };
class Triangle : public Shape {
public:
Triangle(double h, double w) :Shape(h,w) {};
double getarea() { return height*width*0.5; }};
int main() {
//create objects
Rectangle Rec(10, 20);
Triangle Tri(2, 3);
//create boost bind function
boost::function<double(double, double)> g1;
g1 = boost::bind(boost::mem_fn(&Shape::getarea), Rec);
//print area and g
cout << Rec.getarea()<<" should be equal to " << g1<< '\n';
//create list
vector<shared_ptr<Shape>> Plist;
Plist.push_back(make_shared<Rectangle>(Rec));
Plist.push_back(make_shared<Triangle>(Tri));
//print each element from the vector list
for (auto iter = Plist.begin(); iter != Plist.end(); iter ++ ) {
boost::function<double(double, double)> g2;
g2= boost::bind(boost::mem_fn(& .... , &(**iter));
//where in dots we need Classtype_of_**iter::getarea
cout << (**iter).getarea()<<"should be equal to " << g2<< '\n';
}
}
You... forget to invoke the functions...
for (auto iter = Plist.begin(); iter != Plist.end(); iter++) {
boost::function<double()> g2;
g2 = boost::bind(&Shape::getarea, iter->get());
cout << (*iter)->getarea() << " should be equal to " << g2() << '\n';
}
What you saw what the implicit conversion to bool (http://www.boost.org/doc/libs/1_60_0/doc/html/boost/function.html#idm45507164686720-bb)
Note also I fixed the signature of g1 and g2: Live On Coliru.
Some further improvements (remove the need for the g2 in the loop?):
auto getarea = boost::mem_fn(&Shape::getarea);
for (auto iter = Plist.begin(); iter != Plist.end(); iter++) {
cout << (*iter)->getarea() << " should be equal to " << getarea(**iter) << '\n';
}
Or, indeed in c++11:
for (auto& s : Plist)
cout << s->getarea() << " should be equal to " << getarea(*s) << '\n';
By this time, you'd wonder why you have this accessor when you can just use the member.

Finding incorrect implementation of JudyArray

I'm trying to give a better error report (possible bug) for this case (about judySArray give incorrect result, but I don't know which key that give incorrect result).
The code here from this folder, note on this blog. Dependencies: judySArray.h and cedar.h
// judy.cpp
#include "deps/judySArray.h"
#include <string>
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
typedef judySArray<double> MSD;
const int MAX_DATA = 12000000;
const char i2ch[] = {'0','1','2','3','4','5','6','7','8','9','a','B','c','D','e','F'};
int get_first_digit(double d) {
while(d > 10) d /= 10;
return d;
}
string to_rhex(int v) {
char hex[32];
int start = 0;
while(v>0) {
hex[start] = i2ch[v%16];
v /= 16;
++start;
}
hex[start] = 0;
return hex;
}
void add_or_inc(MSD &m, const string& key,double set, double inc, int& ctr) {
const char* cstr = key.c_str();
double it = m.find(cstr);
if(!it) {
m.insert(cstr,set);
return;
}
m.insert(cstr,it+inc);
++ctr;
}
int main() {
MSD m(64);
int dup1 = 0, dup2 = 0, dup3 = 0;
for(int z=MAX_DATA;z>0;--z) {
int val2 = MAX_DATA-z;
int val3 = MAX_DATA*2-z;
string key1 = to_string(z);
string key2 = to_string(val2);
string key3 = to_rhex(val3);
add_or_inc(m,key1,z,val2,dup1);
add_or_inc(m,key2,val2,val3,dup2);
add_or_inc(m,key3,val3,z,dup3);
}
cout << dup1 << ' ' << dup2 << ' ' << dup3 << endl;
int total = 0, verify = 0, count = 0;
for(auto &it = m.begin();m.success(); m.next()) {
total += get_first_digit(it.value);
verify += strlen((const char *) it.key);
count += 1;
}
cout << total << ' ' << verify << ' ' << count << endl;
}
other implementation (map, unordered_map, hat-trie and cedar) give correct result:
6009354 6009348 611297
36186112 159701682 23370001
but judy didn't:
6009354 6009348 611297
36186112 159701681 23370000
The problem is, which key that have incorrect result?
I've tried to build a code that insert those keys on another data structure (that is cedar), but that incorrect keys still not detected:
// judy.cpp
#include "deps/judySArray.h"
#include <string>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <vector>
using namespace std;
typedef judySArray<double> MSD;
const int MAX_DATA = 12000000;
const char i2ch[] = {'0','1','2','3','4','5','6','7','8','9','a','B','c','D','e','F'};
int get_first_digit(double d) {
while(d > 10) d /= 10;
return d;
}
string to_rhex(int v) {
char hex[32];
int start = 0;
while(v>0) {
hex[start] = i2ch[v%16];
v /= 16;
++start;
}
hex[start] = 0;
return hex;
}
void add_or_inc(MSD &m, const string& key,double set, double inc, int& ctr) {
const char* cstr = key.c_str();
double it = m.find(cstr);
if(!it) {
m.insert(cstr,set);
return;
}
m.insert(cstr,it+inc);
++ctr;
}
#include "deps/cedar.h"
class MSD2 {
public:
vector<double> data;
typedef cedar::da<int> CI;
CI da;
bool exists(const string& key,double &old) {
int idx = -1;
bool found = da.exactMatchExists(key.c_str(),key.size(),&idx);
if(found) old = data[idx];
return found;
}
void insert(const string& key,double val) {
da.update(key.c_str(),key.size(),data.size());
data.push_back(val);
}
void update(const string& key,double val) {
int idx = -1;
bool found = da.exactMatchExists(key.c_str(),key.size(),&idx);
if(found) {
data[idx] = val;
return;
}
insert(key,val);
}
};
void add_or_inc(MSD2 &m, const string& key,double set, double inc, int& ctr) {
double old;
if(!m.exists(key,old)) {
m.insert(key,set);
return;
}
m.update(key,old+inc);
++ctr;
}
int main() {
MSD m(64);
MSD2 m2;
int dup1 = 0, dup2 = 0, dup3 = 0;
int vup1 = 0, vup2 = 0, vup3 = 0;
for(int z=MAX_DATA;z>0;--z) {
int val2 = MAX_DATA-z;
int val3 = MAX_DATA*2-z;
string key1 = to_string(z);
string key2 = to_string(val2);
string key3 = to_rhex(val3);
add_or_inc(m,key1,z,val2,dup1);
add_or_inc(m,key2,val2,val3,dup2);
add_or_inc(m,key3,val3,z,dup3);
add_or_inc(m2,key1,z,val2,vup1);
add_or_inc(m2,key2,val2,val3,vup2);
add_or_inc(m2,key3,val3,z,vup3);
}
cout << dup1 << ' ' << dup2 << ' ' << dup3 << endl;
cout << vup1 << ' ' << vup2 << ' ' << vup3 << endl;
int total = 0, verify = 0, count = 0;
int xotal = 0, xerify = 0, xount = 0;
union { int i; int x; } b;
size_t from = 0, p = 0;
char key[256] = {0};
for (b.i = m2.da.begin(from, p); b.i != MSD2::CI::CEDAR_NO_PATH; b.i = m2.da.next(from, p)) {
double it2 = m2.data[b.x]; // <-- find cedar's
xotal += get_first_digit(it2);
m2.da.suffix(key,p,from);
xerify += strlen(key);
xount += 1;
double it = m.find(key); // <-- find judy's
if(it != it2) { // if value doesn't match, print:
cout << "mismatch value for " << key << " : " << it2 << " vs " << it << endl;
}
}
for(auto &it = m.begin();m.success(); m.next()) {
total += get_first_digit(it.value);
verify += strlen((const char *) it.key);
count += 1;
}
cout << total << ' ' << verify << ' ' << count << endl;
cout << xotal << ' ' << xerify << ' ' << xount << endl;
}
compile with: clang++ -std=c++11 judy-findbug.cpp (or g++ -std=c++11)
the output would be:
6009354 6009348 611297
6009354 6009348 611297
36186112 159701681 23370000 <-- judy's
36186112 159701682 23370001 <-- cedar's
cedar has one more value than judy's (that is correct), but it didn't detected by the code above..
How to find that incorrect key(s)?
The bug on the code is someone (me) uncomment the assert(value != 0).
The bug was Karl's Judy implementation should not store null values (0 value).
Solution: use Doug Baskins' Judy implementation.

Resources