How to write equation of the form x'=f(x,t) where t appears explicitly in odeint - odeint

I'm trying to use odeint to solve a differential equation of the form:
y[0]'(r)=y1,
y[1]'(r)=f(y,r)
where t appears explicitly. How do I write "r" in the code for the equation?
See example below
typedef std::vector< double > state_type;
class phieq{
double lambda, mu, g, sigma, rv;
public:
phieq(double mlambda, double mmu, double mg, double msigma, double mrv) : lambda(mlambda), mu(mmu), g(mg), sigma(msigma), rv(mrv) {}
void operator() (const state_type &y , state_type &dydr , const double /* t */)
{ dydr[0] = y[1];
dydr[1] = -((2.0*y[1])/r)+lambda*y[0]*y[0]*y[0]-(mu*mu)*y[0];
}
};

r is your independent variable in this case. odeint originates from dynamical systems so it uses t (for time) for this in its example. In your case you should write
void operator() (const state_type &y , state_type &dydr , const double r)
and then you can use r in the expressions below.

Related

Implicit vector conversion in ImGui (ImVec <--> glm::vec)

I am trying to get the implicit conversion between ImGui's (ImVec) and glm's (glm::vec) vector types working.
In here I read, that I have to change the following lines in the imconfig.h file:
#define IM_VEC2_CLASS_EXTRA \
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
operator MyVec4() const { return MyVec4(x,y,z,w); }
The first line makes sense to me, but I don't see the point of the second making a new constructor for MyVec.
Since I really have no idea what is going on here, I just tried to replace MyVecN with either glm::vecN or vecN, but neither works.
Also I don't get why there are these backslashes, I guess they're to comment out? Either way, I removed them, and it still didn't work.
The compiler ends up throwing tons of errors so I don't know where the problem is.
You have to defined/include your struct before including imgui:
// define glm::vecN or include it from another file
namespace glm
{
struct vec2
{
float x, y;
vec2(float x, float y) : x(x), y(y) {};
};
struct vec4
{
float x, y, z, w;
vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {};
};
}
// define extra conversion here before including imgui, don't do it in the imconfig.h
#define IM_VEC2_CLASS_EXTRA \
constexpr ImVec2(glm::vec2& f) : x(f.x), y(f.y) {} \
operator glm::vec2() const { return glm::vec2(x, y); }
#define IM_VEC4_CLASS_EXTRA \
constexpr ImVec4(const glm::vec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
operator glm::vec4() const { return glm::vec4(x,y,z,w); }
#include "imgui/imgui.h"
And the backslashes \ are just line breaks in the #define, to specify a continuous definition

values changing while saving or reading float and double values to yaml file using opencv

Setup: opencv 3.2 on ubuntu 18.04.
I save an int, a float and a double value using YAML file. The values of the float and the double in the YAML file is different from the values which are written by the program.
#include <opencv2/core/core.hpp>
int main(int ac, char** av)
{
cv::FileStorage fs("file.yaml", cv::FileStorage::WRITE); // create FileStorage object
int a = 1;
float b = 0.2;
double c = 0.3;
fs << "a" << a;
fs << "b" << b;
fs << "c" << c;
fs.release(); // releasing the file.
return 0;
}
The file.yaml reads
%YAML:1.0
---
a: 1
b: 2.0000000298023224e-01
c: 2.9999999999999999e-01
Also when I read the above YAML file using code belong I get altered values for the float and the double values.
#include <opencv2/core/core.hpp>
#include <iostream>
int main(int ac, char** av)
{
cv::FileStorage fs("file.yaml", cv::FileStorage::READ); // create FileStorage object
int a; float b; double c;
fs["a"] >> a;
fs["b"] >> b;
fs["c"] >> c;
std::cout << "a, b, c="<< a << ","<< b << ","<< c << std::endl;
fs.release(); // releasing the file.
return 0;
}
Output of the above program and the saved YAML file:
a, b, c=1,0.2,0.3
My question is how to read and write float and double values from/to YAML files using opencv without value alteration
The values of the float and the double in the YAML file is different from the values which are written by the program.
float and double are represented using a floating-point format with a binary base. The values 0.2 and 0.3 are not representable in these formats. The nearest representable values are 0.20000000298023223876953125 and 0.299999999999999988897769753748434595763683319091796875.
The numerals written to the file, “2.0000000298023224e-01” and “2.9999999999999999e-01” differ from the represented values (shown above) but contain sufficiently many digits to uniquely identify the represented values. When read back, the resulting float and double values should equal the values shown above.
Also when I read the above YAML file using code belong [below?] I get altered values for the float and the double values.
What do you mean by “altered values”? According to the question, the output of the “code below” is “a, b, c=1,0.2,0.3”. While 0.2 and 0.3 differ from the represented values shown above, they are what we expect to be output by default when those values are sent to std::cout. Most likely, what has happened is that, when “2.0000000298023224e-01” was read from the file, 0.20000000298023223876953125 was stored in the float b, and writing this to std::cout produced “0.2”, as expected, and similarly for double c and 0.3. What do you believe differs from this?

Expanding of UMat into data, step and the offset

while i was looking into the OpenCV code of ORB I encountered following part:
return hr_ker.args(ocl::KernelArg::ReadOnlyNoSize(imgbuf),
ocl::KernelArg::PtrReadOnly(layerinfo),
ocl::KernelArg::PtrReadOnly(keypoints),
ocl::KernelArg::PtrWriteOnly(responses),
nkeypoints).run(1, globalSize, 0, true);
This part loads the kernel arguments an runs the kernel (ORB_HarrisResponses). the UMat imgbuf expands to the following parameters (found this statement on a question on stakoverflow)
uchar* data, int step, int offset,
Kernel:
ORB_HarrisResponses(__global const uchar* imgbuf, int imgstep, int imgoffset0,
__global const int* layerinfo, __global const int* keypoints,
__global float* responses, int nkeypoints, int blockSize, float scale_sq_sq, float HARRIS_K )
{}
My question is, how can i acces these values in my code (Host Code). I´m looking for something like :
Umat test
test.data //Mat correspondant
test.step

histogram kernel memory issue

I am trying to implement an algorithm to process images with more than 256 bins.
The main issue to process histogram in such case comes from the impossibility to allocate more than 32 Kb as local tab in the GPU.
All the algorithms I found for 8 bits per pixel images use a fixed size tab locally.
The histogram is the first process in that tab then a barrier is up and at last an addition is made with the output vector.
I am working with IR image which has more than 32K bins of dynamic.
So I cannot allocate a fixed size tab inside the GPU.
My algorithm use an atomic_add in order to create directly the output histogram.
I am interfacing with OpenCV so, in order to manage the possible case of saturation my bins use floating points. Depending on the ability of the GPU to manage single or double precision.
OpenCV doesn't manage unsigned int, long, and unsigned long data type as matrix type.
I have an error... I do think this error is a kind of segmentation fault.
After several days I still have no idea what can be wrong.
Here is my code :
histogram.cl :
#pragma OPENCL EXTENSION cl_khr_fp64: enable
#pragma OPENCL EXTENSION cl_khr_int64_base_atomics: enable
static void Atomic_Add_f64(__global double *val, double delta)
{
union {
double f;
ulong i;
} old;
union {
double f;
ulong i;
} new;
do {
old.f = *val;
new.f = old.f + delta;
}
while (atom_cmpxchg ( (volatile __global ulong *)val, old.i, new.i) != old.i);
}
static void Atomic_Add_f32(__global float *val, double delta)
{
union
{
float f;
uint i;
} old;
union
{
float f;
uint i;
} new;
do
{
old.f = *val;
new.f = old.f + delta;
}
while (atom_cmpxchg ( (volatile __global ulong *)val, old.i, new.i) != old.i);
}
__kernel void khist(
__global const uchar* _src,
const int src_steps,
const int src_offset,
const int rows,
const int cols,
__global uchar* _dst,
const int dst_steps,
const int dst_offset)
{
const int gid = get_global_id(0);
// printf("This message has been printed from the OpenCL kernel %d \n",gid);
if(gid < rows)
{
__global const _Sty* src = (__global const _Sty*)_src;
__global _Dty* dst = (__global _Dty*) _dst;
const int src_step1 = src_steps/sizeof(_Sty);
const int dst_step1 = dst_steps/sizeof(_Dty);
src += mad24(gid,src_step1,src_offset);
dst += mad24(gid,dst_step1,dst_offset);
_Dty one = (_Dty)1;
for(int c=0;c<cols;c++)
{
const _Rty idx = (_Rty)(*(src+c+src_offset));
ATOMIC_FUN(dst+idx+dst_offset,one);
}
}
}
The function Atomic_Add_f64 directly come from here and there
main.cpp
#include <opencv2/core.hpp>
#include <opencv2/core/ocl.hpp>
#include <fstream>
#include <sstream>
#include <chrono>
int main()
{
cv::Mat_<unsigned short> a(480,640);
cv::RNG rng(std::time(nullptr));
std::for_each(a.begin(),a.end(),[&](unsigned short& v){ v = rng.uniform(0,100);});
bool ret = false;
cv::String file_content;
{
std::ifstream file_stream("../test/histogram.cl");
std::ostringstream file_buf;
file_buf<<file_stream.rdbuf();
file_content = file_buf.str();
}
int output_flag = cv::ocl::Device::getDefault().doubleFPConfig() == 0 ? CV_32F : CV_64F;
cv::String atomic_fun = output_flag == CV_32F ? "Atomic_Add_f32" : "Atomic_Add_f64";
cv::ocl::ProgramSource source(file_content);
// std::cout<<source.source()<<std::endl;
cv::ocl::Kernel k;
cv::UMat src;
cv::UMat dst = cv::UMat::zeros(1,65536,output_flag);
a.copyTo(src);
atomic_fun = cv::format("-D _Sty=%s -D _Rty=%s -D _Dty=%s -D ATOMIC_FUN=%s",
cv::ocl::typeToStr(src.depth()),
cv::ocl::typeToStr(src.depth()), // this to manage case like a matrix of usigned short stored as a matrix of float.
cv::ocl::typeToStr(output_flag),
atomic_fun.c_str());
ret = k.create("khist",source,atomic_fun);
std::cout<<"check create : "<<ret<<std::endl;
k.args(cv::ocl::KernelArg::ReadOnly(src),cv::ocl::KernelArg::WriteOnlyNoSize(dst));
std::size_t sz = a.rows;
ret = k.run(1,&sz,nullptr,false);
std::cout<<"check "<<ret<<std::endl;
cv::Mat b;
dst.copyTo(b);
std::copy_n(b.ptr<double>(0),101,std::ostream_iterator<double>(std::cout," "));
std::cout<<std::endl;
return EXIT_SUCCESS;
}
Hello I arrived to fix it.
I don't really know where the issue come from.
But if I suppose the output as a pointer rather than a matrix it work.
The changes I made are these :
histogram.cl :
__kernel void khist(
__global const uchar* _src,
const int src_steps,
const int src_offset,
const int rows,
const int cols,
__global _Dty* _dst)
{
const int gid = get_global_id(0);
if(gid < rows)
{
__global const _Sty* src = (__global const _Sty*)_src;
__global _Dty* dst = _dst;
const int src_step1 = src_steps/sizeof(_Sty);
src += mad24(gid,src_step1,src_offset);
ulong one = 1;
for(int c=0;c<cols;c++)
{
const _Rty idx = (_Rty)(*(src+c+src_offset));
ATOMIC_FUN(dst+idx,one);
}
}
}
main.cpp
k.args(cv::ocl::KernelArg::ReadOnly(src),cv::ocl::KernelArg::PtrWriteOnly(dst));
The rest of the code is the same in the two files.
For me it work fine.
If someone know why it work when the ouput is declared as a pointer rather than a vector (matrix of one row) I am interested.
Nevertheless my issue is fix :).

Is there any way to convert an Eigen::Matrix back to itk::image?

I used Eigen library to convert several itk::image images into matrices, and do some dense linear algebra computations on them. Finally, I have the output as a matrix, but I need it in itk::image form. Is there any way to do this?
const unsigned int numberOfPixels = importSize[0] * importSize[1];
float* array1 = inverseU.data();
float* localBuffer = new float[numberOfPixels];
std::memcpy(localBuffer, array1, numberOfPixels);
const bool importImageFilterWillOwnTheBuffer = true;
importFilter->SetImportPointer(localBuffer,numberOfPixels,importImageFilterWillOwnTheBuffer);
importFilter->Update();
inverseU is the Eigen library matrix (float), importSize is the size of this matrix. When I give importFilter->GetOutput(), and write the result to file, the image I get is like this, which is not correct.
This is the matrix inverseU.
https://drive.google.com/file/d/0B3L9EtRhN11QME16SGtfSDJzSWs/view?usp=sharing . It is supposed to give a retinal fundus image in image form, I got the matrix after doing deblurring.
Take a look at the ImportImageFilter of itk. In particular, it may be used to build an itk::Image starting from a C-style array (example).
Someone recently asked how to convert a CImg image to ITK image. My answer might be a starting point...
A way to get the array out of a matrix A from Eigen may be found here :
double* array=A.data();
EDIT : here is a piece of code to turn a matrix of float into a png image saved with ITK. First, the matrix is converted to an itk Image of float. Then, this image is rescaled an cast to a image of unsigned char, using the RescaleIntensityImageFilter as explained here. Finally, the image is saved in png format.
#include <iostream>
#include <itkImage.h>
using namespace itk;
using namespace std;
#include <Eigen/Dense>
using Eigen::MatrixXf;
#include <itkImportImageFilter.h>
#include <itkImageFileWriter.h>
#include "itkRescaleIntensityImageFilter.h"
void eigen_To_ITK (MatrixXf mat)
{
const unsigned int Dimension = 2;
typedef itk::Image<unsigned char, Dimension> UCharImageType;
typedef itk::Image< float, Dimension > FloatImageType;
typedef itk::ImportImageFilter< float, Dimension > ImportFilterType;
ImportFilterType::Pointer importFilter = ImportFilterType::New();
typedef itk::RescaleIntensityImageFilter< FloatImageType, UCharImageType > RescaleFilterType;
RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();
typedef itk::ImageFileWriter< UCharImageType > WriterType;
WriterType::Pointer writer = WriterType::New();
FloatImageType::SizeType imsize;
imsize[0] = mat.rows();
imsize[1] = mat.cols();
ImportFilterType::IndexType start;
start.Fill( 0 );
ImportFilterType::RegionType region;
region.SetIndex( start );
region.SetSize( imsize );
importFilter->SetRegion( region );
const itk::SpacePrecisionType origin[ Dimension ] = { 0.0, 0.0 };
importFilter->SetOrigin( origin );
const itk::SpacePrecisionType spacing[ Dimension ] = { 1.0, 1.0 };
importFilter->SetSpacing( spacing );
const unsigned int numberOfPixels = imsize[0] * imsize[1];
const bool importImageFilterWillOwnTheBuffer = true;
float * localBuffer = new float[ numberOfPixels ];
float * it = localBuffer;
memcpy(it, mat.data(), numberOfPixels*sizeof(float));
importFilter->SetImportPointer( localBuffer, numberOfPixels,importImageFilterWillOwnTheBuffer );
rescaleFilter ->SetInput(importFilter->GetOutput());
rescaleFilter->SetOutputMinimum(0);
rescaleFilter->SetOutputMaximum(255);
writer->SetFileName( "output.png" );
writer->SetInput(rescaleFilter->GetOutput() );
writer->Update();
}
int main()
{
const int rows = 42;
const int cols = 90;
MatrixXf mat1(rows, cols);
mat1.topLeftCorner(rows/2, cols/2) = MatrixXf::Zero(rows/2, cols/2);
mat1.topRightCorner(rows/2, cols/2) = MatrixXf::Identity(rows/2, cols/2);
mat1.bottomLeftCorner(rows/2, cols/2) = -MatrixXf::Identity(rows/2, cols/2);
mat1.bottomRightCorner(rows/2, cols/2) = MatrixXf::Zero(rows/2, cols/2);
mat1+=0.1*MatrixXf::Random(rows,cols);
eigen_To_ITK (mat1);
cout<<"running fine"<<endl;
return 0;
}
The program is build using CMake. Here is the CMakeLists.txt :
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(ItkTest)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
# to include eigen. This path may need to be changed
include_directories(/usr/local/include/eigen3)
add_executable(MyTest main.cpp)
target_link_libraries(MyTest ${ITK_LIBRARIES})

Resources