Yaml File Format used in OpenCV - opencv

Here is a example (part of code) from OpenCV (https://docs.opencv.org/3.4.0/d4/da4/group__core__xml.html):
test.yml
%YAML:1.0
---
frameCount: 5
read.cpp
#include "opencv2/opencv.hpp"
#include <time.h>
using namespace cv;
using namespace std;
int main()
{
FileStorage fs("test.yml", FileStorage::READ);
int frameCount = (int) fs["frameCount"];
cout << frameCount << endl;
return 0;
}
Given the code, it works well and reads the yaml file. But when I remove %YAML:1.0, the code throws:
OpenCV Error: Unknown error code -49 (Input file is empty) in cvOpenFileStorage, file /home/pengfei/Documents/opencv-3.3.1/modules/core/src/persistence.cpp, line 4484
terminate called after throwing an instance of 'cv::Exception'
what(): /home/pengfei/Documents/opencv-3.3.1/modules/core/src/persistence.cpp:4484: error: (-49) Input file is empty in function cvOpenFileStorage
[1] 27146 abort (core dumped) ./Read
But I checked the yaml.org. There is no rule stating %YAML:1.0 is necessary. (http://yaml.org/start.html)
**My questions are (updated according to answer from #zindarod ): **
1. Is this OpenCV specific feature??
Yes, this is OpenCV specific requirment.
const char* yaml_signature = "%YAML";
const char* json_signature = "{";
const char* xml_signature = "<?xml";
OpenCV checks the file signature, then decide how to interpret the file.
2. How to know the yaml version I should use??
The yaml verison doesn't matter too much.
But it's better to use 1.0 specification. Probably OpenCV cannot parse other new specifications.

In OpenCV-3.3.1 in function cvOpenFileStorage located at /modules/core/src/persistence.cpp:
...
else
{
if( mem )
{
fs->strbuf = filename;
fs->strbufsize = fnamelen;
}
size_t buf_size = 1 << 20;
const char* yaml_signature = "%YAML";
const char* json_signature = "{";
const char* xml_signature = "<?xml";
char buf[16];
icvGets( fs, buf, sizeof(buf)-2 );
char* bufPtr = cv_skip_BOM(buf);
size_t bufOffset = bufPtr - buf;
if(strncmp( bufPtr, yaml_signature, strlen(yaml_signature) ) == 0)
fs->fmt = CV_STORAGE_FORMAT_YAML;
else if(strncmp( bufPtr, json_signature, strlen(json_signature) ) == 0)
fs->fmt = CV_STORAGE_FORMAT_JSON;
else if(strncmp( bufPtr, xml_signature, strlen(xml_signature) ) == 0)
fs->fmt = CV_STORAGE_FORMAT_XML;
else if(fs->strbufsize == bufOffset)
CV_Error(CV_BADARG_ERR, "Input file is empty");
...
OpenCV checks for file signature (json, yaml and xml). The version of YAML does not matter, as long as the first line contains the string "%YAML" in it.

Related

opencv imread exit code 0xC0000409

The code is:
#include <iostream>
#include <opencv2/opencv.hpp>
int main (int argc, char** argv) {
auto path = "C:/Users/huhua/Pictures/11.jpg";
auto img = cv::imread(path);
if (img.empty()) {
std::cout << "is empty" << std::endl;
return 1;
}
cv::imshow("demo", img);
cv::waitKey(0);
return 0;
}
The 11.jpg exist. And if I use another 11.bmp. It works well.
After debug. The error is throw at libjpeg-trubo/src/jdatasr.c
fill_input_buffer(j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr)cinfo->src;
size_t nbytes;
// error is throw at here
nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
// ...
}
Is my libjpeg issue??
How to fix this?
The 11.jpg image:
Update:
The OpenCV info
Update on 2021/10/19:
The reason is I set the cmake_toolchain_path after project(xxx). I should set the cmake_toolchain_path before project.
https://github.com/microsoft/vcpkg/discussions/20802

Why the interpreter complains that library named "math" does not exist?

Why the interpreter complains that library named "math" does not exist?
As far as I know, this library is loaded when invoking luaL_newstate on Lua-5.3.5.
#include "lua.hpp"
#include <iostream>
#include <assert.h>
#include <fstream>
int main()
{
struct lua_State *L = luaL_newstate();
int ret;
std::string fileName("co.lua");
if(fileName.empty())
{
std::cout << "the filename is empty" << std::endl;
return -1;
}
std::ifstream fileScript(fileName, fileScript.in|std::ios::ate);
if(!fileScript.is_open())
{
std::cout << "open file failed" << std::endl;
return -2;
}
size_t size = fileScript.tellg();
if(size <= 0)
{
std::cout << "file has no valid content" << std::endl;
return -3;
}
std::string textCont(size, '\0');
fileScript.seekg(0);
fileScript.read(&textCont[0], size);
if((ret=luaL_loadbuffer(L, textCont.data(), textCont.length(), "co.lua")) == LUA_OK)
{
if((ret=lua_pcall(L, 0, LUA_MULTRET, 0)) != LUA_OK)
{
std::cout << "error in invoking lua_pcall():" << ret << std::endl;
if(lua_isstring(L, -1))
{
const char *errMsg = lua_tostring(L, -1);
lua_pop(L, 1);
std::cout << "script run encounter err:" << errMsg << std::endl;
}
}
}
}
Here is the code snippet(it's very simple) for the file named "co.lua":
a = 1;
b=2;
a=a+1;
math.sin(a)
Here is the error message in the console:
error in invoking lua_pcall():2
script run encounter err:[string "co.lua"]:29: attempt to index a nil value (global 'math')
The documentation states that you need to call luaL_openlibs or luaL_requiref which does not seem to be the case with your posted program.
To have access to these libraries, the C host program should call the luaL_openlibs function, which opens all standard libraries.
Alternatively (emphasis mine):
Alternatively, the host program can open them individually by using luaL_requiref to call:
luaopen_base (for the basic library)
luaopen_package (for the package library)
luaopen_coroutine (for the coroutine library)
luaopen_string (for the string library)
luaopen_utf8 (for the UTF8 library)
luaopen_table (for the table library)
luaopen_math (for the mathematical library)
luaopen_io (for the I/O library)
luaopen_os (for the operating system library)
luaopen_debug (for the debug library).
These functions are declared in lualib.h.
So change your program's first few lines to something like below.
You also need to compare the return value from luaL_newstate with NULL and handle that error condition.
int main()
{
struct lua_State *L = luaL_newstate();
if( L == NULL ) {
puts( "Lua failed to initialize." );
exit(1);
}
luaL_openlibs( L );
// etc

Searching Text in Memory without Visual Component in C++ Builder

I am using C++Builder 10.3 with the VCL 32bit platform. I need to know the best way to search a text file in memory. I wrote the code below which opens a text file into the RichEdit component and searches for and selects some text. The RichEdit is intended to be used as a Visual Component. The TMemoryStream and TStringStream are used in memory but do not offer the methods FindText, SelStart, SelLength and SelText. Can you show how to do this in memory?
UnicodeString MyCrumb;
int StartPos=0, ToEnd=0, FoundAt=0, StartCrumb=0;
TSearchTypes mySearchTypes = TSearchTypes();
RichEdit1->Lines->LoadFromFile( "CrumbFile.txt" );
ToEnd = RichEdit1->Text.Length();
FoundAt = RichEdit1->FindText(L"CrumbStore", StartPos, ToEnd, mySearchTypes);
StartPos = FoundAt+10;
FoundAt = RichEdit1->FindText("crumb", StartPos, ToEnd, mySearchTypes);
StartPos = FoundAt+8;
StartCrumb = FoundAt+8;
FoundAt = RichEdit1->FindText("}", StartPos, ToEnd, mySearchTypes);
EndPos = FoundAt-1;
RichEdit1->SelStart = StartPos;
RichEdit1->SelLength = ( EndPos-StartPos );
MyCrumb = RichEdit1->SelText;
The VCL way is to use TStringList class instead of visual components. However, entire file will be loaded in the memory.
#include <iostream>
#include <memory>
using namespace std;
void FindTextVcl()
{
unique_ptr<TStringList> txt(new TStringList());
txt->LoadFromFile(L"Example.txt"); // Use appropriate TEncoding if need
for (int line_num = 0; line_num != txt->Count; line_num++)
{
int pos = txt->Strings[line_num].Pos("there");
if (pos > 0)
{
cout << "Found at line " << line_num + 1 << ", position " << pos << endl;
break;
}
}
}
The standard library way is like the following example (use wstring and wifstream for UTF-16).
This works for big files because only current string is loaded in the memory.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void FindTextStd()
{
ifstream txt("Example.txt");
if (txt.is_open())
{
size_t pos = 0;
size_t line_num = 0;
string line;
while (getline(txt, line))
{
line_num++;
pos = line.find("there");
if (pos != string::npos)
{
cout << "Found at line " << line_num << ", position " << pos + 1 << endl;
break;
}
}
}
}

Dicom to .PLY Conversion using VTK

I am trying to convert a DICOM file into PLY format using VTK to further convert it into .pcd (point cloud format). I have followed the example provided here.
However in the above example the code is supposed to change .vtu format into .ply format. I changed the code to convert the .dcm format into .ply format as shown below. The build succeeded and the exe file is working as well, however, it does not write the required output file. Can anyone please point out where did I go wrong??
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkDICOMImageReader.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkPLYWriter.h>
int main(int argc, char *argv[])
{
if(argc < 3)
{
std::cerr << "Required arguments: input.vtp output.ply" << std::endl;
return EXIT_FAILURE;
}
std::string inputFileName = argv[1];
std::string outputFileName = argv[2];
// Read the DICOM file in the specified directory.
vtkSmartPointer<vtkDICOMImageReader> reader =
vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetFileName(inputFilename.c_str());
reader->Update();
vtkSmartPointer<vtkPLYWriter> writer = vtkSmartPointer<vtkPLYWriter>::New();
writer->SetFileName(outputFileName.c_str());
writer->SetInputConnection(reader->GetOutputPort());
writer->Update();
return EXIT_SUCCESS;
}
Below is an example of a simple contouring of a DICOM file and extraction of the largest connected area of polydata from the Marching Cubes filter then saved as a PLY format file. This should answer your question.
`
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkDICOMImageReader.h>
#include "vtkMarchingCubes.h"
#include "vtkPolyDataConnectivityFilter.h"
#include <vtkPLYWriter.h>
int main(int argc, char *argv[])
{
if(argc < 3)
{
std::cerr << "Required arguments: input.dcm output.ply" << std::endl;
return EXIT_FAILURE;
}
std::string inputFileName = argv[1];
std::string outputFileName = argv[2];
// Read the DICOM file in the specified directory.
vtkSmartPointer<vtkDICOMImageReader> reader =
vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetFileName(inputFilename.c_str());
reader->Update();
//arb. threshold for bone based on CT Hounsfield Units
float isoValue = 400.0
vtkSmartPointer<vtkMarchingCubes> surface = vtkSmartPointer<vtkMarchingCubes>::New();
surface->SetInputConnection(reader->GetOutputPort());
surface->ComputeNormalsOn();
surface->SetValue(0, isoValue);
surface->Update()
// To remain largest region
vtkSmartPointer<vtkPolyDataConnectivityFilter> confilter =
vtkSmartPointer<vtkPolyDataConnectivityFilter>::New();
confilter->SetInputConnection(surface->GetOutputPort());
confilter->SetExtractionModeToLargestRegion();
confilter->Update();
vtkSmartPointer<vtkPLYWriter> writer = vtkSmartPointer<vtkPLYWriter>::New();
writer->SetFileName(outputFileName.c_str());
writer->SetInputConnection(confilter->GetOutputPort());
writer->Update();
return EXIT_SUCCESS;
}

saving an image sequence from video using opencv2

Newbie question and yes I have spent a lot of time sifting through similar questions and Answers with no luck.
What I am trying to do is save frames from a video file in a sequential order. I have managed to save one image using c and I cannot seem to save images after that. I have started using c++ in opencv instead of c and all I can do is view the video and not save any jpg's from it.
I am using opencv2.4.4a on mac if that helps.
below is my c example
#include <stdio.h>
#include <stdlib.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>
using namespace cv;
using namespace std;
int main (int argc, char** argv)
{
//initializing capture from file
CvCapture * capture = cvCaptureFromAVI ("/example/example.mov");
//Capturing a frame
IplImage* img = 0;
if(!cvGrabFrame(capture)) //capture a frame
{
printf)Could not grab a fram\n\7");
exit(0);
}
img=cvRerieveFrame(capture); //retrieve the captured frame
//writing an image to a file
if (!cvSaveImage("/frames/test.jpg", img))
printf("Could not save: %s\n","test.jpg");
//free resources
cvReleaseCapture(&capture);
}
Thank you in advance
edit to the above.
I have added to the above code which results in an image to be saved with the test.jpg and then gets rewritten with the next frame. How do I tell opencv to not copy over the last image and rename the next frame to test_2.jpg eg, test_1.jpg, test_2.jpg and so on?
double num_frames = cvGetCaptureProperty (capture, CV_CAP_PROP_FRAME_COUNT);
for (int i = 0; i < (int)num_frames; i++)
{
img = cvQueryFrame(capture);
cvSaveImage("frames/test.jpg", img);
}
cvReleaseCapture(&capture);
}
This is my code... I tryed a lot and finally made it
this is c++ using opencv 3... hope it works
#include "opencv2/opencv.hpp"
#include <sstream>
#include <iostream>
using namespace cv;
using namespace std;
Mat frame,img;
int counter;
int main(int,char**)
{
VideoCapture vid("video3.avi");
while (!vid.isOpened())
{
VideoCapture vid("video2.MOV");
cout << "charging" << endl;
waitKey(1000);
}
cout << "Video opened!" << endl;
while(1)
{
stringstream file;
vid.read(frame);
if(frame.empty()) break;
file << "/home/pedro/workspace/videoFrame/Debug/frames/image" << counter << ".jpg";
counter++;
imwrite(file.str(),frame);
char key = waitKey(10);
if ( key == 27)
{break;}
}
}
Use an index that will keep track of the number part in the filename. In the image capturing loop, add the index with the filename and build the final filename.
here is an example :
while(1)
{
cap.read ( frame);
if( frame.empty()) break;
imshow("video", frame);
char filename[80];
sprintf(filename,"C:/Users/cssc/Desktop/testFolder/test_%d.png",i);
imwrite(filename, frame);
i++;
char key = waitKey(10);
if ( key == 27) break;
}
This is my way to do in Python3.0. Have to have CV2 3+ version for it to work.
This function saves images with frequency given.
import cv2
import os
print(cv2.__version__)
# Function to extract frames
def FrameCapture(path,frame_freq):
# Path to video file
video = cv2.VideoCapture(path)
success, image = video.read()
# Number of frames in video
fps = int(video.get(cv2.CAP_PROP_FPS))
length = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
print('FPS:', fps)
print('Extracting every {} frames'.format(frame_freq))
print('Total Frames:', length)
print('Number of Frames Saved:', (length // frame_freq) + 1)
# Directory for saved frames
try:
frame_dir = path.split('.')[0]
os.mkdir(frame_dir)
except FileExistsError:
print('Directory ({}) already exists'.format(frame_dir))
# Used as counter variable
count = 0
# checks whether frames were extracted
success = 1
# vidObj object calls read
# function extract frames
while count < length :
video.set(cv2.CAP_PROP_POS_FRAMES , count)
success, image = video.read()
# Saves the frames with frame-count
cv2.imwrite(frame_dir + "/frame%d.jpg" % count, image)
count = count + frame_freq

Resources