Read metadata from a PNG file with imagemagick++ - imagemagick

I want to do this (as subject indicates) using the imagemagick++ API. I specifically want to read the focal length used by the (DSLR camera) to shoot. [EDIT] This is part of a program that manipulates the images [END EDIT]
I know I can do it through a system call, invoking the command identify -verbose <image_filename> (e.g., with popen so that I can read the output and look for the line containing FocalLengthIn35mmFilm). But this is gross for two reasons:
It is just gross and inefficient.
identify is an ImageMagick utility, so if that command can do it, then I should be able to do it using ImageMagick's API.
Notice that, as the subject says, I am working with PNG files; however, a solution that could work with any lossless image format would be preferred.

ImageMagick is not a EXIF editor, so the best option is to dump the profile EXIF payload into libexif API. But if you are just peaking at a value, you can use ImageMagick's percent escape mechanics to retrieve a value.
For example:
#include <iostream>
#include <string>
#include <Magick++.h>
using namespace Magick;
int main()
{
InitializeMagick((const char *)nullptr);
Image img("DSCF2763.JPG");
Blob data;
MagickCore::SetImageOption(img.imageInfo(), "format", "%[EXIF:FocalLengthIn35mmFilm]");
img.write(&data, "INFO");
std::string value((const char *)data.data(), data.length());
std::cout << value << std::endl;
}
The above is the same as the CLI command:
convert DSCF2763.JPG -define "format=%[EXIF:FocalLengthIn35mmFilm]" info:
Update
An even easier way would be to use Magick::Image.attribute()
#include <iostream>
#include <string>
#include <Magick++.h>
using namespace Magick;
int main()
{
InitializeMagick((const char *)nullptr);
Image img("DSCF2763.JPG");
std::string value = img.attribute("EXIF:FocalLengthIn35mmFilm");
std::cout << value << std::endl;
}

Related

<< operator is crashing program with exit code 0 at some random step of printing

I am working with opencv 3.4 and CLion 2017.3. I have built opencv with mingw and cmake, and i can use the library in my code without problem. Howewher, when i try to run this test code in main.cpp that just prints the matrix, I get a crash at some step of execution of << operator:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat img(7,6, CV_8UC3, Scalar(126,0,255));
cout << img << endl << endl << endl;
cout << "end!";
If i run the code more than once i get these results:
If i add dimentions up to some big number, the code crashes on some ~30 line or earlier
EDIT: Apparently, the problem is not related to opencv, i get this output when printing numbers from 1 to 1000 in a loop:
After googling anything console-related about CLion i found other corrupted console output problems.
The proposed solution to them was to tweak the run.processes.with.pty setting in the idea.properties file. see this YouTrack answer for details.
That solved my issue, too.

gpu::cvtColor(input_gpu, output_gpu, CV_BGR2GRAy)

I am trying to learn how to use the GPU programs in OpenCV. I have built everything with CUDA and if I run
cout << " Number of devices " << cv::gpu::getCudaEnabledDeviceCount() << endl;
I get the answer 1 device so at least something seems to work. However, I try the following peace of code, it just prints out the message and then nothing happens. It gets stuck on
cv::gpu::cvtColor(input_gpu, output_gpu, CV_BGR2GRAY);
Here is the code
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/gpu/gpu.hpp>
#include <opencv2/opencv.hpp>
using std::cout;
using std::endl;
int main(void){
cv::Mat input = cv::imread("image.jpg");
if (input.empty()){
cout << "Image Not Found" << endl;
return -1;
}
cv::Mat output;
// Declare the input and output GpuMat
cv::gpu::GpuMat input_gpu;
cv::gpu::GpuMat output_gpu;
cout << "Number of devices: " << cv::gpu::getCudaEnabledDeviceCount() << endl;
// Copy the input cv::Mat to device.
// Device memory will be allocated automatically according to the parameters of input image
input_gpu.upload(input);
// Convert the input image to grayScale on GPU
cv::gpu::cvtColor(input_gpu, output_gpu, CV_BGR2GRAY);
//// Copy the result from GPU back to host
output_gpu.download(output);
cv::imshow("Input", input);
cv::imshow("Output", output);
cv::waitKey(0);
return 0;
}
I just found this issue and it seems to be a problem with the Maxwell architecture, but that post is over a year old. Has anybody else experienced the same problem? I am using windows 7, Visual Studio 2013 and an Nvidia Geforce GTX 770.
/ Erik
Ok, I do not really know what the problem was, but in CMake, I changed the CUDA_GENERATION to Kepler, which is the micro architecture of my GPU, then I recompiled it, and now the code works as it should.
Interestingly, there were only Fermi and Kepler to choose, so I do not know if one will get problem with Maxwell.
/ Erik

CUDA not running in OpenCV even after successful build

I am trying to build OpenCV 2.4.10 on a Win 8.1 machine with CUDA 6.5. I have other third part libraries as well and they have installed successfully. I ram a simple GPU based program and I got this error No GPU found or the library was compiled without GPU support. I also ran the sample exe files like performance_gpu.exe that were built during the installation and I got the same error. I also had WITH_CUDA flag checked. Following are the flags (related to CUDA) that were set during the CMAKE build.
WITH_CUDA : Checked
WITH_CUBLAS : Checked
WITH_CUFFT : Checked
CUDA_ARCH_BIN : 1.1 1.2 1.3 2.0 2.1(2.0) 3.0 3.5
CUDA_ARCH_PTX : 3.0
CUDA_FAST_MATH : Checked
CUDA_GENERATION : Auto
CUDA_HOST_COMPILER : $(VCInstallDir)bin
CUDA_SPERABLE_COMPILATION : Unchecked
CUDA_TOOLKIT_ROOT_DIR : C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v6.5
Another thing is that in some posts I have read that along with CUDA the built takes a lot of time. My build takes ~ 3 Hrs where maximum time is taken up during the compilation of .cu files. I have not got any errors as far as I know during the compilation of those files.
In some posts I have seen that people talk about a directory names gpu inside the build directory but I don't see any in mine!
I am using Visual Studio 2013.
What could be the issue? Please help!
UPDATE:
I again tried to build opencv and this time before starting the build I added the bin, lib and include directories of CUDA. After the build in E:\opencv\build\bin\Release I ran gpu_perf4au.exe and I got this output
[----------]
[ INFO ] Implementation variant: cuda.
[----------]
[----------]
[ GPU INFO ] Run test suite on GeForce GTX 860M GPU.
[----------]
Time compensation is 0
OpenCV version: 2.4.10
OpenCV VCS version: unknown
Build type: release
Parallel framework: tbb
CPU features: sse sse2 sse3 ssse3 sse4.1 sse4.2 avx avx2
[----------]
[ GPU INFO ] Run on OS Windows x64.
[----------]
*** CUDA Device Query (Runtime API) version (CUDART static linking) ***
Device count: 1
Device 0: "GeForce GTX 860M"
CUDA Driver Version / Runtime Version 6.50 / 6.50
CUDA Capability Major/Minor version number: 5.0
Total amount of global memory: 2048 MBytes (2147483648 bytes)
GPU Clock Speed: 1.02 GHz
Max Texture Dimension Size (x,y,z) 1D=(65536), 2D=(65536,65536), 3
D=(4096,4096,4096)
Max Layered Texture Size (dim) x layers 1D=(16384) x 2048, 2D=(16384,16
384) x 2048
Total amount of constant memory: 65536 bytes
Total amount of shared memory per block: 49152 bytes
Total number of registers available per block: 65536
Warp size: 32
Maximum number of threads per block: 1024
Maximum sizes of each dimension of a block: 1024 x 1024 x 64
Maximum sizes of each dimension of a grid: 2147483647 x 65535 x 65535
Maximum memory pitch: 2147483647 bytes
Texture alignment: 512 bytes
Concurrent copy and execution: Yes with 1 copy engine(s)
Run time limit on kernels: Yes
Integrated GPU sharing Host Memory: No
Support host page-locked memory mapping: Yes
Concurrent kernel execution: Yes
Alignment requirement for Surfaces: Yes
Device has ECC support enabled: No
Device is using TCC driver mode: No
Device supports Unified Addressing (UVA): Yes
Device PCI Bus ID / PCI location ID: 1 / 0
Compute Mode:
Default (multiple host threads can use ::cudaSetDevice() with device simul
taneously)
deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 6.50, CUDA Runtime Ver
sion = 6.50, NumDevs = 1
I thought that every thing was fine but after running this program where I had included all opencv and CUDA directories in its property files,
#include <cv.h>
#include <highgui.h>
#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\gpu\gpu.hpp>
using namespace std;
using namespace cv;
char key;
Mat thresholder (Mat input) {
gpu::GpuMat dst, src;
src.upload(input);
gpu::threshold(src, dst, 128.0, 255.0, CV_THRESH_BINARY);
Mat result_host(dst);
return result_host;
}
int main(int argc, char* argv[]) {
cvNamedWindow("Camera_Output", 1);
CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY);
while (1){
IplImage* frame = cvQueryFrame(capture);
IplImage* gray_frame = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
cvCvtColor(frame, gray_frame, CV_RGB2GRAY);
Mat temp(gray_frame);
Mat thres_temp;
thres_temp = thresholder(temp);
//cvShowImage("Camera_Output", frame); //Show image frames on created window
imshow("Camera_Output", thres_temp);
key = cvWaitKey(10);
if (char(key) == 27){
break; //If you hit ESC key loop will break.
}
}
cvReleaseCapture(&capture);
cvDestroyWindow("Camera_Output");
return 0;
}
I got the error:
OpenCV Error: No GPU support (The library is compiled without CUDA support) in E
mptyFuncTable::mallocPitch, file C:\builds\2_4_PackSlave-win64-vc12-shared\openc
v\modules\dynamicuda\include\opencv2/dynamicuda/dynamicuda.hpp, line 126
Thanks to #BeRecursive for giving me a lead to solve my issue. The CMAKE build log has three unavailable opencv modules namely androidcamera, dynamicuda and viz. I could not find any information on dynamicuda i.e. the module whose unavailability might have caused the error that I mentioned in the question. Instead I searched for viz module and checked how is it installed.
After going through some blogs and forums I found out that viz module has not been included in the pre-built versions of OpenCV. It was recommended to build from source version 2.4.9. I thought to give it a try and I installed it with VS 2013 and CMAKE 3.0.1 but there were many build failures and warnings. Upon further search I found that CMAKE versions 3.0.x aren't recommended for building OpenCV as they are producing many warnings.
At last I decided to switch to VS 2010 and CMAKE 2.8.12.2 and after building the source I got no error and luckily the after adding all executables, libraries and DLLs in the PATH, when I ran my program that I have mentioned above I got no errors but it is running very slowly! So I ran this program:
#include <cv.h>
#include <highgui.h>
#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\gpu\gpu.hpp>
#include <opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
Mat thresholder(Mat input) {
cout << "Beginning thresholding using GPU" << endl;
gpu::GpuMat dst, src;
src.upload(input);
cout << "upload done ..." << endl;
gpu::threshold(src, dst, 128.0, 255.0, CV_THRESH_BINARY);
Mat result_host(dst);
cout << "Thresolding complete!" << endl;
return result_host;
}
int main(int argc, char** argv) {
Mat image, gray_image;
image = imread("desert.jpg", CV_LOAD_IMAGE_COLOR); // Read the file
if (!image.data) {
cout << "Could not open or find the image" << endl;
return -1;
}
cout << "Orignal image loaded ..." << endl;
cvtColor(image, gray_image, CV_BGR2GRAY);
cout << "Original image converted to Grayscale" << endl;
Mat thres_image;
thres_image = thresholder(gray_image);
namedWindow("Original Image", WINDOW_AUTOSIZE);// Create a window for display.
namedWindow("Gray Image", WINDOW_AUTOSIZE);
namedWindow("GPU Threshed Image", WINDOW_AUTOSIZE);
imshow("Original Image", image);
imshow("Gray Image", gray_image);
imshow("GPU Threshed Image", thres_image);
waitKey(0);
return 0;
}
Later I even tested the build on VS 2013 and it also worked.
The GPU based programs are slow due to reasons mentioned here.
So three important things I want to point out:
BUILD from source only
Use a little older version of CMAKE
Prefer VS 2010 for building the binaries.
NOTE:
This might sound weird but all my first BUILDS failed due to some linker error. So, I don't know whether this is work around or not but try to build opencv_gpu before anything and all other modules one by one after that and then build ALL_BUILDS and INSTALL projects.
When you build this way in DEBUG mode you might get an error iff you are building opencv with Python support i.e. "python27_d.lib" otherwise all projects will be built successfully.
WEB SOURCES:
Following are web sources that helped me in solving my problem:
http://answers.opencv.org/question/32502/opencv-249-viz-module-not-there/
http://home.eps.hw.ac.uk/~cgb7/opencv/opencv_tutorial.pdf
http://perso.uclouvain.be/allan.barrea/opencv/opencv.html
http://eavise.wikispaces.com/Building+OpenCV+yourself+on+Windows+7+x64+with+OpenCV+2.4.5+and+CUDA+5.0
https://devtalk.nvidia.com/default/topic/767647/how-do-i-enable-cuda-when-installing-opencv-/
So that is a run time error, being thrown by OpenCV. If you take a look at your CMake log fro your previous question, you can see that one of the Unavailable packages was dynamiccuda, which appears to be what that error is complaining about.
However, I don't have a lot of experience with Windows OpenCV so that could be a red herring. My gut feeling says that you don't have all the libraries correctly on the path. Have you made sure that you have the CUDA lib/include/bin on the PATH? Have you made sure that you have your OpenCV build lib/include directory on the path. Windows has a very simple linking order that essentially just includes the current directory, anything on the PATH and the main Windows directories. So, I would try making sure everything was correctly on the PATH/that you have copied all the correct libraries into the folder.
A note: this is different from a compiling/linking error because it is at RUNTIME. So setting the compiler paths will not help with runtime linking errors.

get matrix of image in opencv

//Open the image
Mat img_rgb = imread("sudoku2.png", CV_LOAD_IMAGE_GRAYSCALE);
if (img_rgb.empty())
{
cout<<"Cannot open the image"<<endl;
return;
}
Mat img_bw = img_rgb > 128;
imwrite("image_bw.jpg", img_bw);
Now, I want to get all pixels of img_bw and save it into a matrix M (int[img_bw.rows][img_bw.cols]). How to do it in C++.
What format ?
The raw byte data in cv::Mat is available from the .ptr() function, ie img_bw.ptr().
Opencv also has an xml and json read and write functions for matrices, just by using the << operator - see opencv tutorial on xml and yaml i/o
EDIT: In c++ you can access pixels with the .at operator.
Use img_data.at<uchar>(x,y) for an unsigned char (CV_8U) pixel and img_data.at<float>(x,y) for a CV_32F image.

low-pass filter in opencv

I would like to know how I can do a low-pass filter in opencv on an IplImage.
For example "boxcar" or something similar.
I've googled it but i can't find a clear solution.
If anyone could give me an example or point me in the right direction on how to implement this in opencv or javacv I would be grateful.
Thx in advance.
Here is an example using the C API and IplImage:
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/highgui/highgui_c.h"
int main()
{
IplImage* img = cvLoadImage("input.jpg", 1);
IplImage* dst=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);
cvSmooth(img, dst, CV_BLUR);
cvSaveImage("filtered.jpg",dst);
}
For information about what parameters of the cvSmooth function you can have a look at the cvSmooth Documentation.
If you want to use a custom filter mask you can use the function cvFilter2D:
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/highgui/highgui_c.h"
int main()
{
IplImage* img = cvLoadImage("input.jpg", 1);
IplImage* dst=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);
double a[9]={ 1.0/9.0,1.0/9.0,1.0/9.0,
1.0/9.0,1.0/9.0,1.0/9.0,
1.0/9.0,1.0/9.0,1.0/9.0};
CvMat k;
cvInitMatHeader( &k, 3, 3, CV_64FC1, a );
cvFilter2D( img ,dst, &k,cvPoint(-1,-1));
cvSaveImage("filtered.jpg",dst);
}
These examples use OpenCV 2.3.1.
The openCV filtering documentation is a little confusing because the functions try and efficently cover every possible filtering technique.
There is a tutorial on using your own filter kernels which covers box filters

Resources