stack around the variable ' ' was corrupted(in opencv) - c++

when I debug this code it does not enter cvundistortpoint and gives me this error:
Stack around the variable 'input' was corrupted.
I've read similar answers to this question but none of them was in OpenCV, does this make any difference?
Is it because of my _src and _dest matrix size?
I've put 'for' loop to see whether _src is being filled or not.
float input [2][2] = {{xR , yR},{xL , yL}};
float src[1][4], dest[1][4];
CvMat _src = cvMat(1, 4, CV_64FC2, src );
CvMat _dest = cvMat(1, 4, CV_64FC2, dest );
for(int k = 0; k<2; k++)
{
for(int l = 0; l < 2; l++)
{
CV_MAT_ELEM(_src,float,0,k*2+l) = input[k][l];
float f =CV_MAT_ELEM(_src,float,0,k*2+l);
cout<<endl<<"undis"<<endl<<f<<endl;
}//end forj
}//end fori
cvUndistortPoints(&_src, &_dest, &_intrinsic1, &_Distortion1);

Related

failed assertion during applying BDCSVD

I am using the following struct in my project and the problem occurs in the second constructor. (I am using Visual Studio 2019.)
struct optimal_subspace {
vector<Eigen::VectorXd> span;
//empty constructor
optimal_subspace() {}
//constructor taking a pointset, the cluster number i and the size of subspaces q
//used for the k-means subspace algorithm on the whole pointset
optimal_subspace(vector<point>& pointset, int i, int q) {
//declare a vector to contain the span
vector<Eigen::VectorXd> subspace_span;
//declare integers n,d to save the dimensions of the current data matrix
int n, d;
//declare integer r to save the minimum of n and d
int r;
//using the constructor of the struct subspacematrix to get the data matrix of cluster i, the cluster mean is already subtracted
subspacematrix sm(pointset, i);
Eigen::MatrixXd m = sm.matrix;
//save the dimensions of m
n = m.rows();
d = m.cols();
//determine min(n,d)
r = min(n, d);
//check if the cluster contains points
if (sm.status == true) {
//use either Jacobi or BDCSVD according to the size of m, declare v to save V from the SVD D = U E V^T or thin SVD
//Jacobi better for matrices smaller than 16x16
Eigen::MatrixXd v;
//if r < q compute the Full decomposition as otherwise there are not enough singular vectors to obtain a q-dimensional subspace
//else compute the thin decomposition
clock_t start = clock();
if (n < 16 & d < 16) {
Eigen::JacobiSVD<Eigen::MatrixXd> svd(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
v = svd.matrixV();
}
else {
Eigen::BDCSVD<Eigen::MatrixXd> svd(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
v = svd.matrixV();
}
clock_t stop = clock();
svd_time += (double) (stop - start) / CLOCKS_PER_SEC;
for (int j = 0; j < min(q, r); j++) {
//V is of the form dxr, so, we take the r columns
subspace_span.push_back(v.col(j));
//currentsubspace.push_back(v.col(j) + mean);
}
//if r < q, we fill the subspaces by taking the coordinates of random points outside the cluster
if (min(q, r) < q) {
vector<int> non_cluster_indices = opp_ind(sm.cluster_indices, pointset.size());
uniform_int_distribution<int> uniform_dist(0, non_cluster_indices.size());
//pick randomly a point outside the cluster and add it
for (int j = min(q, r); j < q; j++) {
Eigen::VectorXd non_cluster_vector = pointset[non_cluster_indices[uniform_dist(mt)]].getcoord();
subspace_span.push_back(non_cluster_vector);
}
//orthonormalize the span
stableGramSchmidt(subspace_span, min(q, r));
}
if (subspace_span.size() == 0) cout << "error: empty subspace added" << endl;
}
span = subspace_span;
}
//constructor taking a pointset, the cluster number i and the size of subspaces q and a vector of indices representing a sample
//used for sampling k-means
optimal_subspace(vector<point>& pointset, int i, int q, vector<int> indices) {
//declare a vector to contain the span
vector<Eigen::VectorXd> subspace_span;
//declare integers n,d to save the dimensions of the current data matrix
int n, d;
//declare integer r to save the minimum of n and d
int r;
//using the constructor of the struct subspacematrix to get the data matrix of cluster i, the cluster mean is already subtracted
subspacematrix sm(pointset, indices, i);
Eigen::MatrixXd m = sm.matrix;
//save the dimensions of m
n = m.rows();
d = m.cols();
//check if the cluster contains points
if (sm.status == true) {
//use either Jacobi or BDCSVD according to the size of m, declare v to save V from the SVD D = U E V^T or thin SVD
//Jacobi better for matrices smaller than 16x16
Eigen::MatrixXd v;
//if r < q compute the Full decomposition as otherwise there are not enough singular vectors to obtain a q-dimensional subspace
//else compute the thin decomposition
clock_t start = clock();
if (n < 16 & d < 16) {
Eigen::JacobiSVD<Eigen::MatrixXd> svd(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
v = svd.matrixV();
}
else {
//ofstream file("problematicmatrix.txt", ofstream::trunc);
//file << sm.matrix.format(CommaInitFmt) << endl;
//file.close();
//Eigen::MatrixXd matrix = load_csv<Eigen::MatrixXd>("problematicmatrix.txt");
Eigen::BDCSVD<Eigen::MatrixXd> svd(sm.matrix, Eigen::ComputeThinU | Eigen::ComputeThinV);
v = svd.matrixV();
}
clock_t stop = clock();
svd_time += (double) (stop - start) / CLOCKS_PER_SEC;
int v_cols = v.cols();
int fill_up_index = min(q, v_cols);
for (int j = 0; j < fill_up_index; j++) {
subspace_span.push_back(v.col(j));
}
//if we don't have enough columns, we fill the subspaces by taking the coordinates of random points outside the cluster
if (fill_up_index < q) {
vector<int> non_cluster_indices = opp_ind(sm.cluster_indices, indices);
uniform_int_distribution<int> uniform_dist(0, non_cluster_indices.size() - 1);
//pick randomly a point outside the cluster and add it
for (int j = fill_up_index; j < q; j++) {
Eigen::VectorXd non_cluster_vector = pointset[non_cluster_indices[uniform_dist(mt)]].getcoord();
subspace_span.push_back(non_cluster_vector);
}
//orthonormalize the span
stableGramSchmidt(subspace_span, fill_up_index);
}
if (subspace_span.size() == 0) cout << "error: empty subspace added" << endl;
}
span = subspace_span;
}
};
I get the following exception:
Unhandled exception at 0x00007FF6CB72BD3B in MAaktuell.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
and when debugging after getting it, I end up in the BDCSVD.h.
I also run it in debug mode and got the following error message:
Assertion failed: index >= 0 && index < size(), file C:\Users\Marcel\Desktop\eigen-3.3.7\eigen-3.3.7\Eigen\src\Core\DenseCoeffsBase.h, line 180
I stored the matrix using the I0 format provided by eigen in a txt.file as follows (and included it in the second constructor, it is commented right now):
ofstream file("problematicmatrix.txt", ofstream::trunc);
ile << sm.matrix.format(CommaInitFmt) << endl;
file.close();
and uploaded it here:
problematic matrix in a txt.file
However, I tried to compute the BDCSVD for this matrix again as follows:
Eigen::MatrixXd matrix = load_csv<Eigen::MatrixXd>("problematicmatrix.txt");
Eigen::BDCSVD<Eigen::MatrixXd> svd(matrix, Eigen::ComputeThinU | Eigen::ComputeThinV);
and then, it works. If I include saving and loading the matrix in my method, it fails again. Can anyone help me finding the error? Why do I end up in the header of BDCSVD, when debugging?

convolution implementation in c++

I want to implement 2D convolution function in C++ by myself, without using filter2D(). I'm trying to iterate all pixels of input image and kernel, then, assign new value to each pixel of dst.
However, I got this error.
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
I found that this error tells I'm accessing nullptr, but I could not solve the problem. Here is my c++ code.
cv::Mat_<float> spatialConvolution(const cv::Mat_<float>& src, const cv::Mat_<float>& kernel)
{
// declare variables
Mat_<float> dst;
Mat_<float> flipped_kernel;
float tmp = 0.0;
// flip kernel
flip(kernel, flipped_kernel, -1);
// multiply and integrate
// input rows
for(int i=0;i<src.rows;i++){
// input columns
for(int j=0;j<src.cols;j++){
// kernel rows
for(int k=0;k<flipped_kernel.rows;k++){
// kernel columns
for(int l=0;l<flipped_kernel.cols;l++){
tmp += src.at<float>(i,j) * flipped_kernel.at<float>(k,l);
}
}
dst.at<float>(i,j) = tmp;
}
}
return dst.clone();
}
To simplify let's suppose you have kernel 3x3
k(0,0) k(0,1) k(0,2)
k(1,0) k(1,1) k(1,2)
k(2,0) k(2,1) k(2,2)
to calculate convolution you are scanning input image (marked as I) from left to fright, from top to bottom
and for every pixel of input image you assign one value calculated from the formula below:
newValue(y,x) = I(y-1,x-1) * k(0,0) + I(y-1,x) * k(0,1) + I(y-1,x+1) * k(0,2)
+ I(y,x-1) * k(1,0) + I(y,x) * k(1,1) + I(y,x+1) * k(1,2) +
+ I(y+1,x-1) * k(2,0) + I(y+1,x) * k(2,1) + I(y+1,x+1) * k(2,2)
------------------x------------>
|
|
| [k(0,0) k(0,1) k(0,2)]
y [k(1,0) k(1,1) k(1,2)]
| [k(2,0) k(2,1) k(2,2)]
|
(y,x) of input Image (I) is anchor point of kernel, to assign new value to I(y,x)
you need to multiply every k coefficient by corresponding point of I - your code doesn't do it.
First you need to create dst matrix with dimenstion as original image, and the same type of pixel.
Then you need to rewrite your loops to reflect formula described above:
cv::Mat_<float> spatialConvolution(const cv::Mat_<float>& src, const cv::Mat_<float>& kernel)
{
Mat dst(src.rows,src.cols,src.type());
Mat_<float> flipped_kernel;
flip(kernel, flipped_kernel, -1);
const int dx = kernel.cols / 2;
const int dy = kernel.rows / 2;
for (int i = 0; i<src.rows; i++)
{
for (int j = 0; j<src.cols; j++)
{
float tmp = 0.0f;
for (int k = 0; k<flipped_kernel.rows; k++)
{
for (int l = 0; l<flipped_kernel.cols; l++)
{
int x = j - dx + l;
int y = i - dy + k;
if (x >= 0 && x < src.cols && y >= 0 && y < src.rows)
tmp += src.at<float>(y, x) * flipped_kernel.at<float>(k, l);
}
}
dst.at<float>(i, j) = saturate_cast<float>(tmp);
}
}
return dst.clone();
}
Your memory access error is presumably happening due to the line:
dst.at<float>(i,j) = tmp;
because dst is not initialized. You can't assign something to that index of the matrix if it has no size/data. Instead, initialize the matrix first, as Mat_<float> is a declaration, not an initialization. Use one of the initializations where you can specify a cv::Size or the rows/columns from the different constructors for Mat (see the docs). For example, you can initialize dst with:
Mat dst{src.size(), src.type()};

FFTW and OpenCV's C++ interface, real and imaginary part in Mat output

I'm trying to code a FFT/IFFT function with FFTW 3.3 and OpenCV 2.1 using the C++ interface. I've seen a lot of examples using the old OpenCV formats and I did a direct conversion, but something doesn't work.
The objective of my function is to return a Mat object with the real part and the imaginary part of the FFT, like dft default OpenCV function does. Here is the code of the function. Program gets blocked with memory problem in the lines that copy im_data to data_in.
Does somebody know what am I doing wrong? Thank you
Mat fft_sr(Mat& I)
{
double *im_data;
double *realP_data;
double *imP_data;
fftw_complex *data_in;
fftw_complex *fft;
fftw_plan plan_f;
int width = I.cols;
int height = I.rows;
int step = I.step;
int i, j, k;
Mat realP=Mat::zeros(height,width,CV_64F); // Real Part FFT
Mat imP=Mat::zeros(height,width,CV_64F); // Imaginary Part FFT
im_data = ( double* ) I.data;
realP_data = ( double* ) realP.data;
imP_data = ( double* ) imP.data;
data_in = ( fftw_complex* )fftw_malloc( sizeof( fftw_complex ) * width * height );
fft = ( fftw_complex* )fftw_malloc( sizeof( fftw_complex ) * width * height );
// Problem Here
for( i = 0, k = 0 ; i < height ; i++ ) {
for( j = 0 ; j < width ; j++ ) {
data_in[k][0] = ( double )im_data[i * step + j];
data_in[k][1] = ( double )0.0;
k++;
}
}
plan_f = fftw_plan_dft_2d( height, width, data_in, fft, FFTW_FORWARD, FFTW_ESTIMATE );
fftw_execute( plan_f );
// Copy real and imaginary data
for( i = 0, k = 0 ; i < height ; i++ ) {
for( j = 0 ; j < width ; j++ ) {
realP_data[i * step + j] = ( double )fft[k][0];
imP_data[i * step + j] = ( double )fft[k][1];
k++;
}
}
Mat fft_I(I.size(),CV_64FC2);
Mat fftplanes[] = {Mat_<double>(realP), Mat_<double>(imP)};
merge(fftplanes, 2, fft_I);
fftw_destroy_plan(plan_f);
fftw_free(data_in);
fftw_free(fft);
return fft_I;
}
You are using step wrong. It is meant to index into Mat::data. Since you already casted Mat::data to double* when assigning it to im_data, you can index into im_data "normally":
data_in[k][0] = im_data[i * width + j];
When using step the correct way to index is:
data_in[k][0] = ( double )I.data[i * step + j];
Update:
Try to access your images row-wise. That way you avoid running into problems with stride/step, while still exploiting fast access:
for (int i = 0; i < I.rows; i++)
{
double* row = I.ptr<double>(i);
for (int j = 0; j < I.cols; j++)
{
// Do something with the current pixel.
double someValue = row[j];
}
}
I know this is old but when you are using fftw you need to initialize fftw_complex *data_in
only after creating the plan for the fft, if i recall correctly when you create the plan it sets all the
*data_in values to 0.
so allocate before the plan and initialize after!
Statement
im_data = ( double* ) I.data;
defines im_data as double pointer to image data.
I think that should be mandatory that I was a double values image.

assignment error with Mat OpenCv

I am working with OpenCV and C++ for a project and I found the following problem: after initializing a mat with the following statement
Mat or_mat=Mat(img->height,img->width,CV_32FC1);
check the following value
or_mat.at <float> (i, j) = atan (fy / fx) / 2 +1.5707963;
After completing returning the mat for the output of the function but when I go to read there are many values ​​that do not correspond to the output. Precise in incorrect values ​​for the I-4.31602e +008 is inserted and if I make a cout the value of the expression is correct. What could be the error??
relevant Code:
Mat or_mat=Mat(img->height,img->width,CV_32FC1);
to angle
if(fx > 0){
or_mat.at<float>(i,j) = atan(fy/fx)/2+1.5707963;
}
else if(fx<0 && fy >0){
or_mat.at<float>(i,j) = atan(fy/fx)/2+3.1415926;
}
else if(fx<0 && fy <0){
or_mat.at<float>(i,j) = atan(fy/fx)/2;
}
else if(fy!=0 && fx==0){
or_mat.at<float>(i,j) = 1.5707963;
}
I have to calculate the local orientation of the fingerprint image, the following code I have omitted several statements and calculations that do not have errors.
I would triple check that you are indexing correctly. The following code shows my initialising a matrix full of zeros, and then filling it with some float using at .at operator. It compiles and runs nicely:
int main()
{
int height = 10;
int width = 3;
// Initialise or_mat to with every element set to zero
cv::Mat or_mat = cv::Mat::zeros(height, width, CV_32FC1);
std::cout << "Original or_mat:\n" << or_mat << std::endl;
// Loop through and set each element equal to some float
float value = 10.254;
for (int i = 0; i < or_mat.rows; ++i)
{
for (int j = 0; j < or_mat.cols; ++j)
{
or_mat.at<float>(i,j) = value;
}
}
std::cout << "Final or_mat:\n" << or_mat << std::endl;
return 0;
}

c++ OpenCV CVCalibrateCamera2 is causing multiple errors

I am making a simple calibration program in C++ using OpenCV. Everything goes fine until I actually try to call CVCalibrateCamera2. At this point, I get one of several errors:
If the number of images which I am using is equal to 4 (which is the number of points being drawn from each image:
OpenCV Error: Sizes of input arguments do not match (Both matrices must have the same number of points) in unknown function, file ......\src\cv\cvfundam.cpp, line 870
If the number of images is below 20:
OpenCV Error: Bad argument (The total number of matrix elements is not divisible by the new number of rows) in unknown function, file ......\src\cxcore\cxarray.cpp, line 2749
Otherwise, if the number of image is 20 or above:
OpenCV Error: Unsupported format or combination of formats (Invalid matrix type) in unknown function, file ......\src\cxcore\cxarray.cpp, line 117
I have checked the arguments for CVCalibrateCamera2 many times, and I am certain that they are of the correct dimensions relative to one another. It seems like somewhere the program is trying to reshape a matrix based on the number of images, but I can't figure out where or why. Any ideas? I am using Eclipse Galileo, MINGW 5.1.6, and OpenCV 2.1.
I am not 100% sure about this, but I don't think your object points can be collinear. In your code, you have
const float points [] [2] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}};
These points are all on the same line (the x-axis). I think the object points must define a plane for cvCalibrateCamera2 to work. This might explain the errors you are seeing.
As far as I know, the OpenCV calibration routines were designed mostly for use with the checkerboard pattern (or some other planar set of object points), I don't know if the same algorithms will work in your situation.
Update:
This is the code which calls CVCalibrateCamera2():
void calibrate(CvMat * object_points, CvMat * image_points, CvMat * intrinsicsMatrix, CvMat * distortionVector){
const int point_count = object_points->rows;
const int image_count = image_points->rows / point_count;
CvMat * const full_object_points = cvCreateMat(image_count * point_count, 3, CV_32FC1);
CvMat * const point_counts = cvCreateMat(image_count, 1, CV_32SC1);
for (int i = 0; i < image_count; i++){
CV_MAT_ELEM(*point_counts, float, i, 0) = point_count;
for (int j = 0; j < point_count; j++){
for (int k = 0; k < 3; k++){
CV_MAT_ELEM(*full_object_points, float, i * point_count + j, k) = CV_MAT_ELEM(*object_points, float, j, k);
}
}
}
cvCalibrateCamera2(full_object_points, image_points, point_counts, cvSize(1, 1), intrinsicsMatrix, distortionVector, NULL, NULL, 0);
}
And this is the piece which collects the point values and passes them to the above function:
int main(){
const float points [] [2] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}};
const int image_count = 5;
const int point_count = sizeof (points) / sizeof(points[1]);
CvMat * const object_points = cvCreateMat(point_count, 3, CV_32FC1);
for (int i = 0; i < point_count; i++){
CV_MAT_ELEM(*object_points, float, i, 0) = points[i][0];
CV_MAT_ELEM(*object_points, float, i, 1) = points[i][1];
CV_MAT_ELEM(*object_points, float, i, 2) = 0;
}
CvMat * const image_points = cvCreateMat(image_count * point_count, 2, CV_32FC1);
collectPoints(setup, image_count, point_count, image_points); // See below about this
CvMat * const intrinsicsMatrix = cvCreateMat(3, 3, CV_32FC1);
CvMat * const distortionVector = cvCreateMat(5, 1, CV_32FC1);
calibrate(object_points, image_points, intrinsicsMatrix, distortionVector);
}
In the above code, collectPoints() is a function making use of a third party library (gl.tter's WiiYourself wiimote library, if it matters). The code is below, but the important thing is that the points returned have values ranging from -.5 to .5.
void collectPoints(wiimote_setup & setup, const int image_count, const int point_count, CvMat * const image_points){
image_points->rows = image_count * point_count;
image_points->cols = 2;
bool A_pressed = false;
for (int i = 0; i < image_count; i++){
while (true){
setup.remote.RefreshState();
if (setup.remote.Button.A()){
if (!A_pressed){
for (int j = 0; j < point_count; j++){
wiimote_state::ir::dot & dot = setup.remote.IR.Dot[j];
CV_MAT_ELEM(*image_points, float, i * point_count + j, 0) = .5 - dot.X;
CV_MAT_ELEM(*image_points, float, i * point_count + j, 1) = .5 - dot.Y;
cout << dot.X <<", " << dot.Y << "\n";
}
cout << "\n";
cout.flush();
A_pressed = true;
break;
}
} else{
A_pressed = false;
}
}
}
}