How To Delete A FileNode In An OpenCV FileStorage Object - opencv

I'm basically reading several fields in an OpenCV FileNode, doing some calculations, and then replacing just one of the fields in the original OpenCV FileNode with the calculated data.
I can't find any methods that allow me to do this. Has anyone done this before?
Thanks for your help!

After some searching, it appears that I cannot append or add to an existing filenode or filestorage object.
However, what you can do is create a new FileStorage object, copy over any existing FileNodes you may want to keep, discard any old fields you do not want, and then save this new FileStorage object with the updated data.
I couldn't find a way to use the latest C++ interface to copy FileNodes, however, I did find a way to use the old deprecated structures to accomplish this. The following will copy mapped FileNode to a new FileStorage object.
cv::FileStorage fileStructure;
fileStructure.open("yourfile.xml", cv::FileStorage::WRITE);
CvFileStorage* fsPtr= fileStructure.operator *(); //gets the underlying pointer
cvWriteFileNode(fsPtr, "CopiedNode", fileNodeObject.operator *(),0);
I hope this helps people who are stuck like I was.
Best,
Paul

In OpenCV 4.0, there is a member function of FileNode
void setValue (int type, const void *value, int len=-1);
I haven't try, but it seems to design for this.

There seems not to be any official way to do this prior OpenCV 4.x. A workaround is to use the underlying basic element:
//type int with value of 5
cv::FileNode node;
CvFileNode* rawNode = *node;
//now the new value is 6
rawNode->data.i = 6;

Related

vector<reference_wrapper> .. things going out of scope? how does it work?

Use case: I am converting data from a very old program of mine to a database friendly format. There are parts where I have to do multiple passes over the old data, because in particular the keys have to first exist before I can reference them in relationships. So I thought why not put the incomplete parts in a vector of references during the first pass and return it from the working function, so I can easily use that vector to make the second pass over whatever is still incomplete. I like to avoid pointers when possible so I looked into std::reference_wrapper<T> which seemes like exactly what I need .. except I don't understand it's behavior at all.
I have both vector<OldData> old_data and vector<NewData> new_data as member of my conversion class. The converting member function essentially does:
//...
vector<reference_wrapper<NewData>> incomplete;
for(const auto& old_elem : old_data) {
auto& new_ref = *new_data.insert(new_data.end(), convert(old_elem));
if(is_incomplete(new_ref)) incomplete.push_back(ref(new_ref));
}
return incomplete;
However, incomplete is already broken immediately after the for loop. The program compiles, but crashes and produces gibberish. Now I don't know if I placed ref correctly, but this is only one of many tries where I tried to put it somewhere else, use push_back or emplace_back instead, etc. ..
Something seems to be going out of scope, but what? both new_data and old_data are class members, incomplete also lives outside the loop, and according to the documentation, reference_wrapper is copyable.
Here's a simplified MWE that compiles, crashes, and produces gibberish:
// includes ..
using namespace std;
int main() {
int N = 2; // works correctly for N = 1 without any other changes ... ???
vector<string> strs;
vector<reference_wrapper<string>> refs;
for(int i = 0; i < N; ++i) {
string& sref = ref(strs.emplace_back("a"));
refs.push_back(sref);
}
for (const auto& r : refs) cout << r.get(); // crash & gibberish
}
This is g++ 10.2.0 with -std=c++17 if it means anything. Now I will probably just use pointers and be done, but I would like to understand what is going on here, documentation / search does not seem to help..
The problem here is that you are using vector data structure which might re-allocate memory for the entire vector any time that you add an element, so all previous references on that vector most probably get invalidated, you can resolve your problem by using list instead of vector.

JNA pointer to pointer mapping

I am working on a Java binding for the excellent libvips
Using this function all is fine:
VipsImage *in;
in = vips_image_new_from_file( test.jpg, NULL )
vips_image_write_to_file( in, "out.jpg", NULL )
So mapped in Java:
Pointer vips_image_new_from_file(String filename,String params);
But I have a problem when the parameter like this:
VipsImage *in;
VipsImage *out;
vips_invert( in, &out, NULL )
vips_image_write_to_file( out, "out.jpg", NULL )
I have tried:
int vips_resize(Pointer in, PointerByReference out, Double scale, String params);
Pointer in = vips_image_new_from_file("file.png",null);
PointerByReference ptr1 = new PointerByReference();
vips_invert(in, ptr1, null);
vips_image_write_to_file( ptr1.getValue(), "fileout.png", null);
But doesn't work. The ptr1.getValue() does not contains the expected result.
How can I do it?
Thanks
I'm the libvips maintainer, a Java binding would be great!
But I think you might be taking the wrong approach. I think you are trying a straight wrap of the C API, but that's going to be tricky to do well, since it makes use of a lot of C-isms that don't map well to Java. For example, in C you can write:
VipsImage *image;
if (!(image = vips_image_new_from_file("somefile.jpg",
"shrink", 2,
"autorotate", TRUE,
NULL)))
error ...;
ie. the final NULL marks the end of a varargs name / value list. Here I'm asking the jpeg loader to do a x2 shrink during load, and to apply any Orientation tags it finds in the EXIF.
libvips has a lower-level API based on GObject which is much easier to bind to. There's some discussion and example code in this issue, where someone is making a C# binding using p/invoke.
https://github.com/jcupitt/libvips/issues/558
The code for the C++ and PHP bindings might be a useful reference:
https://github.com/jcupitt/libvips/tree/master/cplusplus
https://github.com/jcupitt/php-vips-ext
That's a PHP binding for the entire library in 1800 lines of C.
I'd be very happy to help if I can. Open an issue on the libvips tracker:
https://github.com/jcupitt/libvips/issues

Load Trained SVM – Emgu CV

I am somewhat new to SVMs and object recognition, and am currently attempting to train an SVM using Emgu CV 3.0, save it to a file, and then load it (for use in HOGDescriptor.SetSVMDetector).
However, among other problems, I cannot find a way to load the SVM after I have saved it.
So far, my code basically does the following:
SVM myFirstSVM = new SVM();
// do some stuff, set some parameters...
myFirstSVM.Train(someParameters);
myFirstSVM.Save("filePath");
From here, the problem lies with reloading the SVM after being saved. I have checked several help topics and pages, and the only related things I could find pertained to OpenCV, which used the following method:
SVM mySecondSVM;
mySecondSVM.load("filePath");
However, I could find no method ".load()" in Emgu 3.0, although it appeared to be present in previous versions. Is there an equivalent of this OpenCV method in Emgu 3.0? I would assume there is, and I am sure it is fairly simple, but I cannot for the life of me find it.
For EmguCV 3.0.0, the Save/Load functionality doesn't seem to be supported (Load doesn't exist), you could use Write/Read instead.
A function to save an SVM model:
public static void SaveSVMToFile(SVM model, String path) {
if (File.Exists(path)) File.Delete(path);
FileStorage fs = new FileStorage(path, FileStorage.Mode.Write);
model.Write(fs);
fs.ReleaseAndGetString();
}
A function to load the SVM model provided the correct path:
public static SVM LoadSVMFromFile(String path) {
SVM svm = new SVM();
FileStorage fs = new FileStorage(path, FileStorage.Mode.Read);
svm.Read(fs.GetRoot());
fs.ReleaseAndGetString();
return svm;
}
I have saved and read the SVM model using the specified functions. But I am working with 3.1.0 version and hope it works for you as well:
I have saved the model in an XML file because the read function works on xml file as far as I know:
Emgu.CV.ML.SVM model = new Emgu.CV.ML.SVM();
model.SetKernel(Emgu.CV.ML.SVM.SvmKernelType.Linear);
model.Type = Emgu.CV.ML.SVM.SvmType.CSvc;
model.C = 1;
model.TermCriteria = new MCvTermCriteria(100, 0.00001);
bool trained = model.TrainAuto(my_trainData, 5);
model.Save("SVM_Model.xml");
and I read the model as follows:
Emgu.CV.ML.SVM model_loaded = new Emgu.CV.ML.SVM();
FileStorage fsr = new FileStorage("SVM_Model.xml", FileStorage.Mode.Read);
model_loaded.Read(fsr.GetFirstTopLevelNode());
and it works correctly.
I hope it works for you so.
For EmguCV 1.5.0:
Load Method (fileName):
Inherited from StatModel
Load the statistic model from file
fileName (String)
The file to load the model from
For EmguCV 3.0+:
Load() is not available, as you can see in the source code: https://sourceforge.net/p/emgucv/code/ci/master/tree/Emgu.CV.ML/StatModel.cs

JavaCV passing Java arrays to functions with #StdVector

I'm trying to call JavaCV's groupRectangles function. Here is the method signature
#Namespace("cv") public static native void groupRectangles(#StdVector("CvRect,cv::Rect") CvRect rectList,
#StdVector IntPointer weights, int groupThreshold, double eps/*=0.2*/);
From the OpenCV documentation, parameters one and two should be std::vector<>'s. I would assume I should pass in some form of Java array (native array, List, etc.), however, the method only has an annotation for a #StdVector, and accepts just a single object.
Can someone please provide a very small snippet of code showing how to properly call this method by passing in two Java lists or arrays or whatever.
I have found the answer through the mailing list here. The only modification I made is below:
final CvRect rectsPointer = new CvRect(faces.size());
for (int i=0; i<faces.size(); ++i)
rectsPointer.position(i).put(faces.get(i));

BMP (OR JPG) to DDS converter programmatically

I have bmp (or jpg) file.
I need to convert it to dds file programmatically (I can use C++, C# with or without .NET; I can try any other language if I would see some clues in it)
I know that there are software that do this, but I need it to integrate into my programm, this should be a part of a longer manipulations on my application.
BTW, my question is:
1) Are there any opensource program that does this, so I can look into the code of it?
2) Are there any tutorials found somewhere in web that can help me to write this code?
I could not found any helpfull information.
Thank you!
I'm sure there are standalone converters you can use calling them via command line, if you need a programmatically solution the easiest way I may think about is to use built-in XNA classes to do the job. Because XNA handles all these file formats you can open source .bmp and then save it back to .dds (using the Texture class):
public static void ConvertToDds(
GraphicsDevice graphicsDevice, string sourcePath, string targetPath)
{
Texture.FromFile(graphicsDevice, sourcePath)
.Save(targetPath, ImageFileFormat.Dds);
}
Things changed with XNA 4.0 (these methods have been removed), try the DDSLib to write and Texture2D to read:
public static void ConvertToDds(
GraphicsDevice graphicsDevice, string sourcePath, string targetPath)
{
using (var stream = File.Open(sourcePath))
{
var texture = Texture2D.FromStream(graphicsDevice, stream);
DDSLib.DDSToFile(targetPath, true, texture, false);
}
}
See linked pages for more details and examples. By the way you can't have C# without .NET!

Resources