i have recently started using opencv and this one has baffled me.
void saveImageSnippet(char *imageName, int height, int width, void* data, int nChannels) //data is char[height * width]
{
char fName[200]="c:\\testimg\\";
FILE *fptr;
IplImage *img;
sprintf(fName,"%s%s.bmp",fName,imageName);
img = cvCreateImageHeader(cvSize(width, height),8/*depth*/,nChannels);
img->imageData=(unsigned char*)data;
cvSaveImage(fName, img); //Unhandled exception
cvReleaseImage(&img);
}
At cvSaveImage : Unhandled exception at 0x6e8e871d in vc2008_1x.exe: 0xC0000005: Access violation reading location 0x745c3a63.
Is there anything i am not doing right?
now an interesting part,
if i add a couple of unused variables, cvSaveImage works just fine
void saveImageSnippet(char *imageName, int height, int width, void* data, int nChannels)
{
int var1, var2; //unused variables
char fName[200]="c:\\testimg\\";
FILE *fptr;
IplImage *img;
sprintf(fName,"%s%s.bmp",fName,imageName);
img = cvCreateImageHeader(cvSize(width, height),8/*depth*/,nChannels);
img->imageData=(unsigned char*)data;
cvSaveImage(fName, img); //now it works fine
cvReleaseImage(&img);
}
please use opencv's c++ api,
avoid anything, that has iplimages in it (especially here on SO !)
#include "opencv2/highgui.hpp" // no, *not* highgui.h !
using namespace cv;
int main()
{
string fName = format("c:\\testimg\\%s.bmp",imageName);
Mat img = imread( fName );
if ( img.empty() )
return -1;
// your image was not loaded
imsave(fName);
return 0;
}
Related
wanna do this:
#include <armadillo>
int main(){
arma::mat mat=arma::randn(5,5);
mat.each_col( [](arma::vec& vec){
vec=arma::sort_index(vec);
} );
return 0;
Is there any way to turn a uvec into vec?
Use arma::conv_to<DesiredType>::from(value).
See below
#include <armadillo>
int main(){
arma::mat mat=arma::randn(5,5);
mat.print("mat");
mat.each_col( [](arma::vec& vec){
vec = arma::conv_to<arma::vec>::from(arma::sort_index(vec));
} );
mat.print("mat");
return 0;
}
With this we can convert the output of arma::sort_index, which is an arma::uvec, into an arma::vec and the assignment will work.
I am facing a problem with running out of memory on my CUDA device. I have detected the cause - in some of my member functions I'm returning a GpuMat constructed over data alocated by myself. Question here is - how do I free this memory?
class Test {
GpuMat test() {
float* dev_ptr = nullptr;
cv::Size size(8192,8192);
cudaMalloc((void**)&dev_ptr, size.width*size.height*sizeof(float));
return GpuMat(size, CV_32FC1, dev_ptr);
}
}
//main
Test t;
while(true) {
size_t free_mem, total_mem;
cudaMemGetInfo(&free_mem, &total_mem);
std::cout << free_mem << std::endl;
cv::namedWindow("test", CV_WINDOW_OPENGL | CV_WINDOW_NORMAL);
cv::imshow("test", t.test());
cv::waitKet(1);
}
You will see decreasing amount of free_mem each iteration (by the same amount).
What I've tried was to create custom allocator and setDefaultAllocator but it didn't work.
class CustomAllocator : public cv::cuda::GpuMat::Allocator
{
float* m_ptr;
public:
CustomAllocator(float* p) : cv::cuda::GpuMat::Allocator(), m_ptr(p) {}
virtual bool allocate(cv::cuda::GpuMat* mat, int rows, int cols, size_t elemsize) override
{
return true;
}
virtual void free(cv::cuda::GpuMat* mat) override
{
cudaFree(m_ptr);
}
};
// more or less looked like this...
GpuMat test() {
float* dev_ptr = nullptr;
cv::Size size(8192,8192);
cudaMalloc((void**)&dev_ptr, size.width*size.height*sizeof(float));
GpuMat retval(size, CV_32FC1, dev_ptr);
retval.setDefaultAllocator(new CustomAllocator(dev_ptr));
return retval;
}
Both Allocator and GpuMat have not so well written docs so any help would be much appreciated.
WHAT SEEMS TO BE WORKING
GpuMat test() {
float* dev_ptr = nullptr;
cv::Size size(8192,8192);
cudaMalloc((void**)&dev_ptr, size.width*size.height*sizeof(float));
// do processing...
// clone data so the GpuMat manages it by itself
auto retval = GpuMat(size, CV_32FC1, dev_ptr).clone();
// free manually allocated memory
cudaFree(dev_ptr);
return retval;
}
As I was writing it down right now I think that optimal would be to allocate GpuMat first and //do processing... using its data.
You're using the particular variant of GpuMat that involves a user-provided allocation. Furthermore, t never goes out of scope in your while loop, so it's not clear to me that any implicit method would work.
Since you are providing that memory allocation with cudaMalloc, my suggestion is that it should be freed by you with cudaFree. So, simplistically, make the dev_ptr a class data member rather than an immediate/temporary variable, and provide a Test::finish() member function that tests this pointer for non-NULL and if so runs cudaFree() on it. Of course if you wanted to handle via a constructor/destructor you might do it differently, and there are probably dozens of variations possible.
Here is one possible approach, coded in browser, not tested:
class Test {
float* dev_ptr;
public:
Test() {dev_ptr = nullptr;}
void finish() { if (dev_ptr != nullptr) cudaFree(dev_ptr);}
GpuMat test() {
cv::Size size(8192,8192);
cudaMalloc((void**)&dev_ptr, size.width*size.height*sizeof(float));
return GpuMat(size, CV_32FC1, dev_ptr);
}
}
//main
Test t;
while(true) {
size_t free_mem, total_mem;
cudaMemGetInfo(&free_mem, &total_mem);
std::cout << free_mem << std::endl;
cv::namedWindow("test", CV_WINDOW_OPENGL | CV_WINDOW_NORMAL);
cv::imshow("test", t.test());
cv::waitKey(1);
t.finish();
}
Alternatively, if you wanted to avoid the explicit call to finish(), and simply wanted to re-allocate, you could do:
class Test {
float* dev_ptr;
public:
Test() {dev_ptr = nullptr;}
GpuMat test() {
cv::Size size(8192,8192);
if (dev_ptr != nullptr) cudaFree(dev_ptr);
cudaMalloc((void**)&dev_ptr, size.width*size.height*sizeof(float));
return GpuMat(size, CV_32FC1, dev_ptr);
}
}
//main
Test t;
while(true) {
size_t free_mem, total_mem;
cudaMemGetInfo(&free_mem, &total_mem);
std::cout << free_mem << std::endl;
cv::namedWindow("test", CV_WINDOW_OPENGL | CV_WINDOW_NORMAL);
cv::imshow("test", t.test());
cv::waitKey(1);
}
ok so here is one for you maybe simple but i am not so sure.
i have the following code and it may be clear what i wish to do by looking at the code.
Arduino.ino
RF myRF; //Creation of RF class.
const int dataSize = 500;
byte storedData[dataSize];
//array is populated through program then the following is called
myRF.populate(storedData);
RF.CCP
const int dataSize = 500;
byte recivedData[dataSize];
void RF::populate(byte reciveddata){
recivedData = reciveddata;
}
RF.H
#include Arduino.h
#ifndef RF_H
#define RF_H
class RF {
public:
RF();
~RF();
void recive();
void send();
void print();
void sendnew(byte Storeddata);
};
#endif
this is however producing an error "byte is not declared"
Hope its clear what i intend to do and hope you can help thanks.
There are two problems in your files:
h file:
#include Arduino.h
You should write
#include <Arduino.h>
c file:
const int dataSize = 500;
byte recivedData[dataSize];
void RF::populate(byte reciveddata){
recivedData = reciveddata;
}
Here you have a big problem. You are declaring recivedData here, but you want to assign it a value coming from another part of the program. This is not how it works.
IMO you have two ways to do this.
1) store just the pointer to the memory; this way is faster and occupies less memory than solution 2, but you have to ensure that the storedData variable you pass in the .ino file is not changed during the function
#include "RF.h" // I hope you already included this
byte *recivedData;
void RF::populate(byte *reciveddata){
recivedData = reciveddata;
}
2) copy the content of the received array to this array; this way you have a copy of the array, so you occupy twice the memory (but you can edit storedData without problems).
#include "RF.h" // I hope you already included this
const int dataSize = 500;
byte recivedData[dataSize];
int recivedDataLength;
void RF::populate(byte *reciveddata, int reciveddatalength){
recivedDataLength = (reciveddatalength>dataSize) ? dataSize : reciveddatalength;
for (int i = 0; i < recivedDataLength; i++)
recivedData[i] = reciveddata[i];
}
I just started learning OpenCV with "Learning OpenCV Computer Vision with the OpenCV Library".
In the first example which demonstrates how to display a picture, it has a line
IplImage* img = cvLoadImage("name.type")
Although the book explains it, I still do not fully know what exactly IplImage* img does.
Does cvLoadImage loads the image to img which IplImage is pointing to? Can anyone explain this to me please? Thank you
img is the name of the variable, might as well be blahblahblah;
IplImage is the type of the variable, it's just a struct that contains the image data itself plus some info (size, color depth, etc.) on the image;
typedef struct _IplImage {
int nSize;
int ID;
int nChannels;
int alphaChannel;
int depth;
char colorModel[4];
char channelSeq[4];
int dataOrder;
int origin;
int align;
int width;
int height;
struct _IplROI* roi;
struct _IplImage* maskROI;
void* imageId;
struct _IplTileInfo* tileInfo;
int imageSize;
char* imageData;
int widthStep;
int BorderMode[4];
int BorderConst[4];
char* imageDataOrigin;
} IplImage;
For more info on IplImage: Other question about IplImage
cvLoadImage provides a pointer to an IplImage, which means it creates an IplImage when it loads it and returns you it's emplacement.
Do not forget to do cvReleaseImage(&img) when you are finished with it, if you do not want to have memory leaks.
I am trying to translate the OpenCV CascadeClassifier tutorial from C++ to Java. Working good in C++. Also this java tutorial is working fine.
But the translation is simply not detecting the face. I don't get explicit errors. I can see the processing of the video input from the webcam (grey/histogram...) and the video display. Cascade load doesn't give error. But the CascadeClassifier call just doesn't return any faces... So, you probably can skip all the code and just go to my CascadeClassifier call, down to public Mat detect(Mat inputframe). As I am new to Java and OpenCV, I paste the rest (I removed anything I felt may not be significant), just in case, but don't mean for you to debug that...
I have also tried this call (and other portions) in many different ways and nothing... running out of ideas...
Thank you!!
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.highgui.VideoCapture;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
class My_Panel extends JPanel{
private static final long serialVersionUID = 1L;
private BufferedImage image;
private CascadeClassifier face_cascade;
// Create a constructor method
public My_Panel(){
super();
String face_cascade_name = "/haarcascade_frontalface_alt.xml";
//String face_cascade_name = "/lbpcascade_frontalface.xml";
//-- 1. Load the cascades
String str;
str = getClass().getResource(face_cascade_name).getPath();
str = str.replace("/C:","C:");
face_cascade_name=str;
face_cascade=new CascadeClassifier(face_cascade_name);
if( !face_cascade.empty())
{
System.out.println("--(!)Error loading A\n");
return;
}
else
{
System.out.println("Face classifier loooaaaaaded up");
}
}
private BufferedImage getimage(){
return image;
}
public void setimage(BufferedImage newimage){
image=newimage;
return;
}
/**
* Converts/writes a Mat into a BufferedImage.
*
* #param matrix Mat of type CV_8UC3 or CV_8UC1
* #return BufferedImage of type TYPE_3BYTE_BGR or TYPE_BYTE_GRAY
*/
public BufferedImage matToBufferedImage(Mat matrix) {
int cols = matrix.cols();
int rows = matrix.rows();
int elemSize = (int)matrix.elemSize();
byte[] data = new byte[cols * rows * elemSize];
int type;
matrix.get(0, 0, data);
switch (matrix.channels()) {
case 1:
type = BufferedImage.TYPE_BYTE_GRAY;
break;
case 3:
type = BufferedImage.TYPE_3BYTE_BGR;
// bgr to rgb
byte b;
for(int i=0; i<data.length; i=i+3) {
b = data[i];
data[i] = data[i+2];
data[i+2] = b;
}
break;
default:
return null;
}
BufferedImage image2 = new BufferedImage(cols, rows, type);
image2.getRaster().setDataElements(0, 0, cols, rows, data);
return image2;
}
public void paintComponent(Graphics g){
BufferedImage temp=getimage();
g.drawImage(temp,10,10,temp.getWidth(),temp.getHeight(), this);
}
public Mat detect(Mat inputframe){
Mat mRgba=new Mat();
Mat mGrey=new Mat();
MatOfRect faces = new MatOfRect();
//MatOfRect eyes = new MatOfRect();
inputframe.copyTo(mRgba);
inputframe.copyTo(mGrey);
Imgproc.cvtColor( mRgba, mGrey, Imgproc.COLOR_BGR2GRAY);
Imgproc.equalizeHist( mGrey, mGrey );
face_cascade.detectMultiScale(mGrey, faces);
//face_cascade.detectMultiScale(mGrey, faces, 1.1, 2, 0|Objdetect.CASCADE_SCALE_IMAGE, new Size(30, 30), new Size(200,200) );
//face_cascade.detectMultiScale(mGrey, faces, 1.1, 2, 2//CV_HAAR_SCALE_IMAGE,
// ,new Size(30, 30), new Size(200,200) );
System.out.println(String.format("Detected %s faces", faces.toArray().length));
return mGrey;
}
}
public class window {
public static void main(String arg[]){
// Load the native library.
System.loadLibrary("opencv_java245");
String window_name = "Capture - Face detection";
JFrame frame = new JFrame(window_name);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,400);
My_Panel my_panel = new My_Panel();
frame.setContentPane(my_panel);
frame.setVisible(true);
//-- 2. Read the video stream
BufferedImage temp;
Mat webcam_image=new Mat();
VideoCapture capture =new VideoCapture(0);
if( capture.isOpened())
{
while( true )
{
capture.read(webcam_image);
if( !webcam_image.empty() )
{
frame.setSize(webcam_image.width()+40,webcam_image.height()+60);
//-- 3. Apply the classifier to the captured image
// At this point I was wondering where this should be done.
// I put it within the panel class, but maybe one could actually
// create a processor object...
webcam_image=my_panel.detect(webcam_image);
//-- 4. Display the image
temp=my_panel.matToBufferedImage(webcam_image);
my_panel.setimage(temp);
my_panel.repaint();
}
else
{
System.out.println(" --(!) No captured frame -- Break!");
break;
}
}
}
return;
}
}
PS.: Other info, just in case:
mGrey is: Mat [ 480*640*CV_8UC1, isCont=true, isSubmat=false, nativeObj=0x19d9af48, dataAddr=0x19dc3430 ]
face is: Mat [ 0*0*CV_8UC1, isCont=false, isSubmat=false, nativeObj=0x194bb048, dataAddr=0x0 ]
I have tried your code and it works fine! You have only one issue with haarcascade_frontalface_alt.xml file location. Try to use a full path to the file:
face_cascade= new CascadeClassifier("D:/HelloCV/src/haarcascade_frontalface_alt.xml");