Hello I am a beginner of C language for microprocessors. I want to read a ''.bmp'' file in order to apply line detection on it. I have declared a function to read the image. This error occurs when compile button is pushed:
#include "esp_camera.h"
#include "Arduino.h"
#include "FS.h" // SD Card ESP32
#include "SD_MMC.h" // SD Card ESP32
#include "soc/soc.h" // Disable brownour problems
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
#include "driver/rtc_io.h"
#include <EEPROM.h> // read and write from flash memory
#include <SPI.h>
void imageReader(const char *imgName,
int *height,
int *width,
int *bitdepth,
unsigned char *header,
unsigned char *_colortable,
unsigned char *buf
) // READ AN IMAGE
{
int i;
fs::FS &fs = SD_MMC; //
FILE *file;
file = fopen(imgName,"rb"); // read imgName file ( it is a picture in .bmp format )
if(!file){
Serial.printf("Unable to read image");
}
for(i=0 ; i<54 ; i++){
header[i]=getc(file);
}
*width = *(int * )& header[18]; // width information of the image
*height = *(int * )& header[22]; // height information of image
*bitdepth = *(int *)& header[28];
if(*bitdepth<=8){
fread(_colortable,sizeof(unsigned char),1024,file);
}
fread(buf,sizeof(unsigned char),( 1600 * 1200 ) ,file);
fclose();
}
It gives this error. too few arguments to function 'int fclose(FILE*)'
The fclose() function needs to know which file to close. You need to tell it that by supplying "file" as an argument. You want to use fclose(file).
Related
I'm trying to save a struct with multiple arma::vec, arma:mat and arma::cube.
struct rdb_struct{
string info;
vec rng_vec;
vec azvec;
cube TSAP;
cube CONV;
cube TVSAP;
mat rd_maxbeam;
mat rd_maxbeam2;
mat rd_maxbeam3;
umat rd_maxbeam_index;
umat rd_maxbeam2_index;
umat rd_maxbeam3_index;
mat rd_maxbeam_azdeg;
mat rd_maxbeam2_azdeg;
mat rd_maxbeam3_azdeg;
};
For the string and vectors, it was somewhat simple to save:
#define ARMA_DONT_USE_WRAPPER
#include <armadillo>
#include <string>
#include <iostream>
#include "H5Cpp.h"
#define ARMA_ALLOW_FAKE_GCC //allows the use of GCC compiled armadillo with ICC compiler
using namespace std;
using namespace arma;
struct rdb_struct{
string info;
//params_struct params;
vec rng_vec;
vec azvec;
cube TSAP;
cube CONV;
cube TVSAP;
mat rd_maxbeam;
mat rd_maxbeam2;
mat rd_maxbeam3;
umat rd_maxbeam_index;
umat rd_maxbeam2_index;
umat rd_maxbeam3_index;
mat rd_maxbeam_azdeg;
mat rd_maxbeam2_azdeg;
mat rd_maxbeam3_azdeg;
};
struct rdb_struct_hdf5{
string info;
// params_struct params;
hvl_t rng_vec;
hvl_t azvec;
hid_t mem_TSAP;
};
int main(void)
{
rdb_struct rdb_data;
rdb_struct_hdf5 rdb_hdf5;
long long unsigned int NR=256;
long long unsigned int ND=450;
long long unsigned int NE=64;
hid_t vlen_double = H5Tvlen_create(H5T_NATIVE_DOUBLE);
rdb_data.info="testing woohoo";
rdb_data.rng_vec=2*ones<vec>(32);
rdb_data.azvec=3*ones<vec>(32);
rdb_data.TSAP=4*ones<cube>(NR,ND,NE);
rdb_data.CONV=5*ones<cube>(NR,ND,NE);
rdb_data.TVSAP=6*ones<cube>(NR,ND,NE);
rdb_data.rd_maxbeam=7*ones<mat>(NR,ND);
rdb_data.rd_maxbeam2=8*ones<mat>(NR,ND);
rdb_data.rd_maxbeam3=9*ones<mat>(NR,ND);
rdb_data.rd_maxbeam_index=10*ones<umat>(NR,ND);
rdb_data.rd_maxbeam2_index=11*ones<umat>(NR,ND);
rdb_data.rd_maxbeam3_index=12*ones<umat>(NR,ND);
rdb_data.rd_maxbeam_azdeg=13*ones<mat>(NR,ND);
rdb_data.rd_maxbeam2_azdeg=14*ones<mat>(NR,ND);
rdb_data.rd_maxbeam3_azdeg=15*ones<mat>(NR,ND);
rdb_hdf5.info=rdb_data.info;
rdb_hdf5.rng_vec.p=rdb_data.rng_vec.memptr();
rdb_hdf5.rng_vec.len=rdb_data.rng_vec.size();
rdb_hdf5.azvec.p=rdb_data.azvec.memptr();
rdb_hdf5.azvec.len=rdb_data.azvec.size();
// the array of each length of multidimentional data.
hsize_t dim_rdb[1];
dim_rdb[0] = sizeof(rdb_hdf5) / sizeof(rdb_struct_hdf5);
// the length of dim
int rank_rdb = sizeof(dim_rdb) / sizeof(hsize_t);
// defining the datatype to pass HDF55
H5::CompType h5_rdb(sizeof(rdb_struct_hdf5));
h5_rdb.insertMember("info", HOFFSET(rdb_struct_hdf5, info), H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
h5_rdb.insertMember("rng_vec", HOFFSET(rdb_struct_hdf5, rng_vec), vlen_double);
h5_rdb.insertMember("azvec", HOFFSET(rdb_struct_hdf5, azvec), vlen_double);
h5_rdb.insertMember("TSAP", HOFFSET(rdb_struct_hdf5, mem_TSAP), cube_double);
// preparation of a dataset and a file.
H5::DataSpace space_rdb(rank_rdb, dim_rdb);
H5::H5File *file = new H5::H5File("data_test.h5", H5F_ACC_TRUNC);
H5::DataSet *dataset_rdb = new H5::DataSet(file->createDataSet("rdb_data", h5_rdb, space_rdb));
// Write
dataset_rdb->write(&rdb_hdf5, h5_rdb);
delete dataset_rdb;
delete file;
return 0;
}
But the mat and cubes have been giving me trouble, mainly because I have no idea what I'm doing with HDF5. It looks like to do what I want, I need to create a H5Tarray_create and insert it into the 'cpmp_type h5_rdb' but everything I have tried has failed to run (it does compile) with the following message:
HDF5-DIAG: Error detected in HDF5 (1.10.4) thread 139735682275136:
#000: ../../../src/H5Tcompound.c line 354 in H5Tinsert(): unable to insert member
major: Datatype
minor: Unable to insert object
#001: ../../../src/H5Tcompound.c line 446 in H5T__insert(): member extends past end of compound type
major: Datatype
minor: Unable to insert object
terminate called after throwing an instance of 'H5::DataTypeIException'
Aborted (core dumped)
This code seems to work but when I try to merge it with my original code it doesn't work, mainly from me not understanding how/why hid_t is used for everything...
#include <armadillo>
#include <string>
#include <iostream>
#include "H5Cpp.h"
#define ARMA_ALLOW_FAKE_GCC //allows the use of GCC compiled armadillo with ICC compiler
using namespace std;
using namespace arma;
int
main (void)
{
long long unsigned int NR=64;
long long unsigned int ND=64;
long long unsigned int NE=64;
hsize_t dims_of_int_array[] = {NR,ND,NE};
hsize_t dims_of_int_dataspace[] = {1};
// int *data = (int *)malloc(4*4*4*sizeof(int));
// int i;
// for (i=0; i<(4*4*4); i++) data[i] = i;
cube data = 4*ones<cube>(NR,ND,NE);
hid_t file = H5Fcreate("multset.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
hid_t mem_h5t = H5Tarray_create(H5T_NATIVE_DOUBLE, 2, dims_of_int_array);
hid_t dataspace = H5Screate_simple(2, dims_of_int_dataspace, NULL);
hid_t dataset = H5Dcreate(file, "data_data", mem_h5t, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
H5Dwrite(dataset, mem_h5t, H5S_ALL, H5S_ALL, H5P_DEFAULT, data.memptr());
H5Dclose(dataset);
H5Sclose(dataspace);
H5Tclose(mem_h5t);
// free(data);
return 0;
}
I did notice the code that is work only works until the cube size becomes too large and starts spitting out errors about contiguous write failed but I think that's a problem for another day. I'm mainly looking for help on how to insert a array datatype into a composite datatype. Any help would be greatly appreciated.
I have created with GIMP a C-Source image dump like the following:
/* GIMP RGBA C-Source image dump (example.c) */
static const struct {
guint width;
guint height;
guint bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
guint8 pixel_data[304 * 98 * 2 + 1];
} example= {
304, 98, 2,
"\206\061\206\061..... }
Is there a way to read this in GIMP again in order to get back the original image? because it doesn't seem possible.
Or does it exist a tool that can do this back-conversion?
EDITED
Following some suggestion I tried to write a simple C programme to make the reverse coversion ending up with something very similar to another code found on internet but both dont work:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "imgs_press.h"
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
using namespace std;
int main(int argc, char** argv) {
int fd;
char *name = "orignal_img.pnm";
fd = open(name, O_WRONLY | O_CREAT, 0644);
if (fd == -1) {
perror("open failed");
exit(1);
}
if (dup2(fd, 1) == -1) {
perror("dup2 failed");
exit(1);
}
// file descriptor 1, i.e. stdout, now points to the file
// "helloworld" which is open for writing
// You can now use printf which writes specifically to stdout
printf("P2\n");
printf("%d %d\n", press_high.width, press_high.height);
for(int x=0; x<press_high.width * press_high.height * 2; x++) {
printf("%d ", press_high.pixel_data[x]);
}
}
As suggested by n-1-8e9-wheres-my-share-m, maybe I need to manipulate the pixels usign the correct decode, but I have no idea how to do that, does anybody have other suggestions?
The image I got is indeed distorted:
Updated Answer
If you want to decode the RGB565 and write a NetPBM format PNM file without using ImageMagick, you can do this:
#include <stdint.h> /* for uint8_t */
#include <stdio.h> /* for printf */
/* tell compiler what those GIMP types are */
typedef int guint;
typedef uint8_t guint8;
#include <YOURGIMPIMAGE>
int main(){
int w = gimp_image.width;
int h = gimp_image.height;
int i;
uint16_t* RGB565p = (uint16_t*)&(gimp_image.pixel_data);
/* Print P3 PNM header on stdout */
printf("P3\n%d %d\n255\n",w, h);
/* Print RGB pixels, ASCII, one RGB pixel per line */
for(i=0;i<w*h;i++){
uint16_t RGB565 = *RGB565p++;
uint8_t r = (RGB565 & 0xf800) >> 8;
uint8_t g = (RGB565 & 0x07e0) >> 3;
uint8_t b = (RGB565 & 0x001f) << 3;
printf("%d %d %d\n", r, g ,b);
}
}
Compile with:
clang example.c
And run with:
./a.out > result.pnm
I have not tested it too extensively beyond your sample image, so you may want to make a test image with some reds, greens, blues and shades of grey to ensure that all my bit-twiddling is correct.
Original Answer
The easiest way to get your image back would be... to let ImageMagick do it.
So, take your C file and add a main() to it that simply writes the 304x98x2 bytes starting at &(example.pixel_data) to stdout:
Compile it with something like:
clang example.c -o program # or with GCC
gcc example.c -o program
Then run it, writing to a file for ImageMagick with:
./program > image.bin
And tell ImageMagick its size, type and where it is and what you want as a result:
magick -size 304x98 RGB565:image.bin result.png
I did a quick, not-too-thorough test of the following code and it worked fine for an image I generated with GIMP. Note it doesn't handle alpha/transparency but that could be added if necessary. Save it as program.c:
#include <unistd.h> /* for write() */
#include <stdint.h> /* for uint8_t */
/* tell compiler what those GIMP types are */
typedef int guint;
typedef uint8_t guint8;
<PASTE YOUR GIMP FILE HERE>
int main(){
/* Work out how many bytes to write */
int nbytes = example.width * example.height * 2;
/* Write on stdout for redirection to a file - may need to reopen in binary mode if on Windows */
write(1, &(example.pixel_data), nbytes);
}
If I run this with the file you provided via Google Drive I get:
I wrote a C++ code which I am converting to a mex file so that I can run from Matlab. My original C++ code displays output of some function declared in third party library. However, when I convert it into mex file, the output seems to be suppressed.
NOTE: output of following command get suppressed
int systemRet = std::system("./genb_test");
Original code:
#include <stdio.h> /* defines FILENAME_MAX */
#include <cstdlib>
#include <iostream>
#ifdef _MSC_VER
#include "direct.h"
#define GetCurrentDir _getcwd // window ??
#else
#include "unistd.h"
#define GetCurrentDir getcwd
#endif
int main()
{
const char *ParentFolder = "/home/dkumar/libtsnnls-2.3.3/tsnnls/";
int res3 = chdir(ParentFolder);
if (res3 == -1){
// The system method failed
std::cout<< "the chdir method has failed \n";
}
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
printf("Could not find current directory " );
// return errno;
}
cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
printf ("The current working directory is %s", cCurrentPath);
printf ("\n");
printf("Now running genb test " );
int systemRet = std::system("./genb_test");
if(systemRet == -1){
// The system method failed
}else{
printf("System command execuated successfully " );
}
return 0;
}
Output from original code:
The current working directory is /home/dkumar/libtsnnls-2.3.3/tsnnls
genb_tests
Creating 100 random test 121 x 89 problems using
the genb algorithm of PJV. Each problem will be given
to the tsnnls method, and the error printed below.
We require an error less than 1e-8 to pass the test.
# M N Error (PJV error) (Spiv error) Result
-----------------------------------------------------------------
1 121 89 1.375271e-15 1.375271e-15 0.000000e+00 pass
2 121 89 1.953126e-15 1.953126e-15 0.000000e+00 pass
3 121 89 4.272569e-15 4.272569e-15 0.000000e+00 pass
4 121 89 1.440234e-15 1.440234e-15 0.000000e+00 pass
5 121 89 2.392671e-15 2.392671e-15 0.000000e+00 pass
.......
.......
98 121 89 4.696796e-15 4.696796e-15 0.000000e+00 pass
99 121 89 1.820247e-15 1.820247e-15 0.000000e+00 pass
100 121 89 1.520109e-15 1.520109e-15 0.000000e+00 pass
100 (of 100) tests passed.
Now running genb test System command execuated successfully
Translated original code to mex file: various input and output (LHS) are left as it is, since I would start using that soon.
#include <matrix.h> // mex
#include <mex.h> // mex
#include <iostream> // Basic I/O
using namespace std; // Basic I/O
/* Definitions to keep compatibility with earlier versions of ML */
#ifndef MWSIZE_MAX
typedef int mwSize;
typedef int mwIndex;
typedef int mwSignedIndex;
#if (defined(_LP64) || defined(_WIN64)) && !defined(MX_COMPAT_32)
/* Currently 2^48 based on hardware limitations */
# define MWSIZE_MAX 281474976710655UL
# define MWINDEX_MAX 281474976710655UL
# define MWSINDEX_MAX 281474976710655L
# define MWSINDEX_MIN -281474976710655L
#else
# define MWSIZE_MAX 2147483647UL
# define MWINDEX_MAX 2147483647UL
# define MWSINDEX_MAX 2147483647L
# define MWSINDEX_MIN -2147483647L
#endif
#define MWSIZE_MIN 0UL
#define MWINDEX_MIN 0UL
#endif
// 'Hello World!' program
#include <stdio.h> /* defines FILENAME_MAX */
#include <cstdlib>
#include <iostream>
#ifdef _MSC_VER
#include "direct.h"
#define GetCurrentDir _getcwd // window ??
#else
#include "unistd.h"
#define GetCurrentDir getcwd
#endif
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
//const char *ParentFolder = "/home/dkumar/All_Matlab_Codes_DKU/";
const char *ParentFolder = "/home/dkumar/libtsnnls-2.3.3/tsnnls/";
//declare variables
mxArray *a_in_m, *b_in_m, *c_out_m, *d_out_m;
const mwSize *dims;
double *a, *b, *c, *d;
int dimx, dimy, numdims;
int i,j;
//associate inputs
a_in_m = mxDuplicateArray(prhs[0]);
b_in_m = mxDuplicateArray(prhs[1]);
//figure out dimensions
dims = mxGetDimensions(prhs[0]);
numdims = mxGetNumberOfDimensions(prhs[0]);
dimy = (int)dims[0]; dimx = (int)dims[1];
//associate outputs
c_out_m = plhs[0] = mxCreateDoubleMatrix(dimy,dimx,mxREAL);
d_out_m = plhs[1] = mxCreateDoubleMatrix(dimy,dimx,mxREAL);
//associate pointers
a = mxGetPr(a_in_m);
b = mxGetPr(b_in_m);
c = mxGetPr(c_out_m);
d = mxGetPr(d_out_m);
std::cout<< "Trying to change the directory "<< "\n";
// COPIED FROM ORIGINAL C++
int res3 = chdir(ParentFolder);
if (res3 == -1){
// The system method failed
std::cout<< "the chdir method has failed \n";
}
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
printf("Could not find current directory " );
// return errno;
}
cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
printf ("The current working directory is %s", cCurrentPath);
printf ("\n");
printf("Now running genb test " );
int systemRet = std::system("./genb_test");
if(systemRet == -1){
// The system method failed
}else{
printf("System command execuated successfully " );
}
// ADDED THIS PART at the suggestion of king_nak
//Capturing the output terminal
FILE * f = popen( "ls -al", "r" );
if ( f == 0 ) {
fprintf( stderr, "Could not execute\n" );
return;
}
const int BUFSIZE = 1000;
char buf[ BUFSIZE ];
while( fgets( buf, BUFSIZE, f ) ) {
fprintf( stdout, "%s", buf );
}
pclose( f );
return;
}
The output is:
>> [c d]=test_snnls_mex(a,b)
Trying to change the directory
The current working directory is /home/dkumar/libtsnnls-2.3.3/tsnnls
Now running genb test
c =
6 7 8
9 10 11
12 13 14
d =
1 4 9
16 25 36
49 64 81
Some help would be appreciated.
Regards,
Dushyant
std::system will start the system's command processor to execute the command. If you have a console app, this will print the output to the current console. This is why you see it in your test program. The output is not passed to the calling program!
In your case, Matlab seems to start the process in the background, where the output is discarded. Try instead opening the process and reading out its output into your program/MEX.
In POSIX, you can use popen (see for example this answer), in Windows you can use ReadPipe (cf. this article)
UPDATE
You have to adjust the code I have linked to. The original code calls ls -al and prints its output to the screen. You have to call your process genb_test!
Use this code to get the output in matlab, instead of your std::system call:
FILE * f = popen( "genb_test", "r" ); // <- call genb_test
if ( f == 0 ) {
fprintf( stderr, "Could not execute\n" );
return;
}
const int BUFSIZE = 1000;
char buf[ BUFSIZE ];
while( fgets( buf, BUFSIZE, f ) ) {
mexPrintf(buf); // <- use mexPrintf to print to matlab
}
pclose( f );
Have you tried the mex-command mexPrintf ?
However, the output won't be printed before the whole mex-program has been executed. Two work-arounds for this are to either use
mexEvalString("disp('Bla')")
or
mexPrintf("Bla")
mexEvalString("drawnow;");
I am trying to run the ezsift library example. The example has name "image_match.cpp".
Here is the code
image_match.cpp
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "../ezsift.h"
using namespace std;
#define USE_FIX_FILENAME 0
int main(int argc, char ** argv)
{
#if USE_FIX_FILENAME
char * file1 = "img1.pgm";
char * file2 = "img2.pgm";
#else
if (argc != 3)
{
printf("Please input two image filenames.\n");
printf("usage: image_match img1 img2\n");
return -1;
}
char file1[255];
char file2[255];
memcpy(file1, argv[1], sizeof(char) * strlen(argv[1]));
file1[strlen(argv[1])] = 0;
memcpy(file2, argv[2], sizeof(char) * strlen(argv[2]));
file2[strlen(argv[2])] = 0;
#endif
// Read two input images
ImageObj<uchar> image1, image2;
if(image1.read_pgm(file1) != 0)
{
printf("Failed to open input image1!\n");
return -1;
}
if(image2.read_pgm(file2) != 0)
{
printf("Failed to open input image2!\n");
return -1;
}
printf("Image 1 loaded. Image size: %d x %d\n", image1.w, image1.h);
printf("Image 2 loaded. Image size: %d x %d\n", image2.w, image2.h);
// Double the original image as the first octive.
double_original_image(true);
// Detect keypoints
list<SiftKeypoint> kpt_list1, kpt_list2;
printf("\nSIFT detection on image 1 ...\n");
sift_cpu(image1, kpt_list1, true);
printf("# keypoints in image1: %d\n", kpt_list1.size());
printf("\nSIFT detection on image 2 ...\n");
sift_cpu(image2, kpt_list2, true);
printf("# keypoints in image2: %d\n", kpt_list2.size());
// Save keypoint list, and draw keypoints on images.
char filename[255];
sprintf(filename, "s_A_keypoints.ppm");
draw_keypoints_to_ppm_file(filename, image1, kpt_list1);
export_kpt_list_to_file("s_A_keypoints.key", kpt_list1, true);
sprintf(filename, "s_B_keypoints.ppm");
draw_keypoints_to_ppm_file(filename, image2, kpt_list2);
export_kpt_list_to_file("s_B_keypoints.key", kpt_list2, true);
// Match keypoints.
list<MatchPair> match_list;
match_keypoints(kpt_list1, kpt_list2, match_list);
// Draw result image.
sprintf(filename, "s_A_B_matching.ppm");
draw_match_lines_to_ppm_file(filename, image1, image2, match_list);
printf("# of matched keypoints: %d\n", match_list.size());
return 0;
}
ezsift.h
#ifndef EZSIFT_H
#define EZSIFT_H
#include "util/image.h"
#include "util/img_io.h"
#include <vector>
#include <list>
.
.
.
#endif
#define DEGREE_OF_DESCRIPTORS (128)
// Enable doubling of original image.
void double_original_image(bool doubleFirstOctave);
// Detect keypoints and extract descriptor.
int sift_cpu(
const ImageObj<uchar> &image,
std::list<SiftKeypoint> & kpt_list,
bool bExtractDescriptors);
// Match keypoints from two keypoint lists.
int match_keypoints(
std::list<SiftKeypoint> & kpt_list1,
std::list<SiftKeypoint> & kpt_list2,
std::list<MatchPair> & match_list);
.
.
.
#endif
(I will not include all the code here, I just wanted to give an idea. It is ease to download the source and see the files that I am talking about)
Also there is a "ezsift.cpp" file with more files in the "util" folder
I'm trying to run it from the terminal. I go to the directory and type "gcc image_match.cpp" but is says that double_original_image, sift_cpu (and all other functions in the header file) are not defined.
more specifically is gives this error:
image_match.cpp:(.text+0x1c7): undefined reference to `double_original_image(bool)'
image_match.cpp:(.text+0x20d): undefined reference to `sift_cpu(ImageObj<unsigned char> const&, std::list<_SiftKeypoint, std::allocator<_SiftKeypoint> >&, bool)'
(these are not the only error of course. It gives same error for all the functions)
I then tried "gcc ../ezsift.cpp image_match.cpp" but the same error.
What am I doing wrong?? I am running ubuntu 14.04.
(expending Cameron's comment into a tested answer)
You need to compile both ezsift.cpp and img_io.cpp with your program (image_match.cpp), while providing the location of the header files (-I\path\to\directory). Here is a working snippet, assuming you are in the examples directory:
g++ image_match.cpp ../ezsift.cpp ../util/img_io.cpp -I.. -o image_match
I am doing a simple project on arm based mini6410. I have debian package installed on mini. My project is to interface one IR motion sensor and I USB webcam with the mini6410. the working will be simple, whenever there will be any motion detected by IR sensor, the webcam will be on for 30 seconds save the images (over write the previous) and then off.
I have already cross comiled the Open CV code using arm-linux-gcc
For IR I am using GPE register.
Here I am stuck with a issue which I am unable to resolve. and even dont know how to resolve. OpenCv code is a cpp file camera.cpp and the file which deals with I/O ports is a C file named sensor.c. Now in that c file I am polling or whatever mechanism to check if the GPE register is 1 or not. If it is one, I should start the Open CV code which will start to capture images. further more this sensor.c file is not to be compiled rather made a module and then insmod on my mini6410.
However I dont know how to write c++ code in a c file. you can say i dont know how to call the OpenCV thing from the C file. as it is a module and within this i cant write the cpp code as then using namespace std and using namespace cv doesnot work.
i am new to embedded stuff and linux it self. so I wanted to know are there some possible solutions.
i am attaching my codes of both files.
This is sensor.c
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-q.h>
#include <mach/gpio-bank-e.h>
#include <mach/map.h>
#include <plat/regs-timer.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <mach/gpio-bank-k.h>
#define RLV 0x0FFF
unsigned Gpe;
unsigned sensor_value;
typedef struct
{
int delay;
} TIM_DEV;
static TIM_DEV TimDev;
static irqreturn_t INTHandler(int irq,void *TimDev)
{
Gpe = readl(S3C64XX_GPEDAT);
Gpe &= ~(0xF<<1);
readl(sensor_value, S3C64XX_GPEDAT);
while (sensor_value == 1)
{//1 means that IR sensor has detected a motion and given a value of +5 V
for (i = 0; i < 30; i++){
//CV_function();
// delay here such that delay(1 s) * 30 = 30 seconds
}
}
return IRQ_HANDLED;
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.write = MyWrite,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
unsigned TimerControl;
unsigned TimerINTControl;
unsigned TimerCNTB;
unsigned TimerCMPB;
unsigned TimerCFG1;
unsigned Ge;
TimerControl = readl(S3C_TCON);
TimerINTControl = readl(S3C_TINT_CSTAT);
TimerCNTB = readl(S3C_TCNTB(0));
TimerCMPB = readl(S3C_TCMPB(0));
TimerCFG1 = readl(S3C_TCFG1);
TimerCFG1 &= ~(S3C_TCFG1_MUX0_MASK);
TimerCNTB = RLV;
TimerCMPB = 0;
writel(TimerCNTB, S3C_TCNTB(0));
writel(TimerCMPB, S3C_TCMPB(0));
writel(TimerCFG1, S3C_TCFG1);
TimerControl |= S3C_TCON_T0MANUALUPD;
TimerINTControl |= S3C_TINT_CSTAT_T0INTEN;
writel(TimerControl, S3C_TCON);
writel(TimerINTControl, S3C_TINT_CSTAT);
TimerControl = readl(S3C_TCON);
TimerControl |= S3C_TCON_T0RELOAD;
TimerControl &= ~S3C_TCON_T0MANUALUPD;
TimerControl |= S3C_TCON_T0START;
writel(TimerControl, S3C_TCON);
//////////////Here I am configuring my GPE as input/////////////
Ge = readl(S3C64XX_GPECON);
Ge &= ~(0xFFFF<<4);
Ge |= (0x0000<<4);
writel(Ge, S3C64XX_GPECON);
/////////////
misc_register(&misc);
ret = request_irq(IRQ_TIMER0, INTHandler, IRQF_SHARED, DEVICE_NAME, &TimDev);
if (ret)
{
return ret;
}
return ret;
}
static void __exit dev_exit(void)
{
free_irq(IRQ_TIMER0, &TimDev);
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("XYZ");
this is camera.cpp
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
int main( int argc, const char** argv )
{CvCapture* capture = 0;
Mat frame, frameCopy, image;
capture = cvCaptureFromCAM( 2 );
if( !capture )
{
cout << "No camera detected" << endl;
}
if( capture )
{
cout << "In capture ..." << endl;
IplImage* iplImg = cvQueryFrame( capture );
frame = iplImg;
if( frame.empty() )
break;
if( iplImg->origin == IPL_ORIGIN_TL )
frame.copyTo( frameCopy );
else
flip( frame, frameCopy, 0 );
cvSaveImage("image.jpg" ,iplImg);
}
cvReleaseCapture( &capture );
return 0;
}
the for loop in the sensor.c file should have my this above code by some means
I hope you get the idea,
Thanks
The missing link in the code shown is a mechanism by which the user-space code shown above can get notification of a change in the GPIO pin detected by the device driver.
There are two obvious ways to achieve this:
Integrate the GPIO pin into the platform's GPIO resources and then use the generic sysfs mechanism from user-space. The Linux kernel GPIO documentation describes both kernel and user-space side of this.
Have your driver expose a sysfs node for the GPIO line. sysfs is fundamental to the Linux Driver Model. I suggest a thorough read of Linux Device Drivers 3rd Edition.
The user-space side of either method is similar: You open the sysfs resource exported by your module and then use either poll() or select() to block until an event occurs.