I have to use an IDS uEye Camera mod. UI1210SE-C under visual c++ 2010 and OpenCV
I need to take a photo every time there is a request by a client, so when I need, I need to take a simple single shot, that I need to save in a OpenCV Mat image.
How do this?
I have download SDK, and initialize camera, that have been recognized by my PC, but I don't understand how take a photo and how save in a Mat without issues
This is my actual code, works but Images are RED tone and not different, but first and second are equal, third different...I don't understand why...
#define CAPTURE_WIDTH 500
#define CAPTURE_HEIGHT 375
//Allocazione della matrice immagine per il frame catturato dalla telecamera
Mat frame(CAPTURE_HEIGHT, CAPTURE_WIDTH,CV_8UC3);
//Variabili di inizializzazione della Telecamera IDS uEye UI1220SE-C
HIDS hCam = 1; //Apre Camera con ID 1
int BITS_PER_PIXEL = 24;
int pWidth = CAPTURE_WIDTH;
int pHeight = CAPTURE_HEIGHT;
SENSORINFO sensor_info;
CAMINFO camera_info;
//puntatori memoria
char* m_pcImageMemory;
int m_lMemoryId;
//Pulizia memoria da foto precedenti
if (hCam != 0){
is_FreeImageMem (hCam,m_pcImageMemory,m_lMemoryId);
is_ExitCamera(hCam);
}
//inizializzazione della telecamera
int initcamera = is_InitCamera(&hCam, NULL);
if(initcamera != IS_SUCCESS)
{
cout<<endl<<"Impossibile inizializzare la telecamera"<<endl;
exit(-1);
}
// Acquisisce informazioni riguardanti la telecamera
int camerainfo = is_GetCameraInfo (hCam, &camera_info);
if(camerainfo != IS_SUCCESS)
{
printf("Impossibile acquisire le informazioni della telecamera");
exit(-1);
}
// Acquisisce informazioni riguardanti il sensore della telecamera
int sensorinfo = is_GetSensorInfo (hCam, &sensor_info);
if(sensorinfo != IS_SUCCESS)
{
printf("Impossibile acquisire le informazioni del sensore");
exit(-1);
}
//Output informazioni camera/sensore
cout<<endl<<"<<< CARATTERISTICHE DELLA TELECAMERA COLLEGATA >>>"<<endl;
cout<<"Numero seriale: " << camera_info.SerNo << endl;
cout << "Produttore: " << camera_info.ID << endl;
cout << "Modello: " << sensor_info.strSensorName << endl;
cout << "Dimensioni massime per l'immagine: " << sensor_info.nMaxWidth << "x" << sensor_info.nMaxHeight << endl << endl;
//Imposta la modalità di colore BGR24
int colormode = is_SetColorMode(hCam, IS_CM_BGR8_PACKED);
//int colormode = is_SetColorMode(hCam, IS_SET_CM_RGB24);
if(colormode != IS_SUCCESS)
{
printf("Impossibile impostare il modo di colore");
exit(-1);
}
//imposta dimensioni immagini che voglio catturare
int pXPos = (sensor_info.nMaxWidth);
int pYPos = (sensor_info.nMaxHeight);
//Inizializzazione Memoria camera
int rit = is_AllocImageMem (hCam,pXPos,pYPos, 24, &m_pcImageMemory, &m_lMemoryId);
if(rit != IS_SUCCESS)
{
cout<<endl<<"IMPOSSIBILE INIZIALIZZARE LA MEMORIA"<<endl;
system("PAUSE");
exit(-1);
}
cout<<endl<<"Memoria inizializzata"<<endl;
//attivazione della locazione di memoria
int rat = is_SetImageMem (hCam, m_pcImageMemory, m_lMemoryId);
if(rat != IS_SUCCESS)
{
cout<<endl<<"IMPOSSIBILE ATTIVARE LA MEMORIA"<<endl;
system("PAUSE");
exit(-1);
}
cout<<endl<<"Memoria Attivata"<<endl;
//impostazioni correzioni di colore
double strenght_factor = 1.0;
int colorcorrection = is_SetColorCorrection(hCam, IS_CCOR_ENABLE, &strenght_factor);
//impostazioni correzione del bianco
double pval = 1;
int whiteb = is_SetAutoParameter(hCam, IS_SET_ENABLE_AUTO_WHITEBALANCE, &pval, 0);
//impostazione della correzione guadagno
double gval = 1;
int gains = is_SetAutoParameter(hCam, IS_SET_ENABLE_AUTO_GAIN, &gval, 0);
//inizio fase cattura immagine
int dummy;
char *pMem, *pLast;
//ciclo di ripetizione
for (int i=0;i<3;i++)
{
int sho = is_FreezeVideo(hCam, IS_WAIT);
if(sho != IS_SUCCESS)
{
cout<<endl<<"IMPOSSIBILE ACQUISIRE DALLA TELECAMERA"<<endl;
system("PAUSE");
exit(-1);
}
if (sho == IS_SUCCESS){
int m_Ret = is_GetActiveImageMem(hCam, &pLast, &dummy);
int n_Ret = is_GetImageMem(hCam, (void**)&pLast);
}
IplImage* tmpImg = cvCreateImageHeader(cvSize (pXPos, pYPos), IPL_DEPTH_8U,3);
tmpImg->imageData = m_pcImageMemory;
frame = cv::cvarrToMat(tmpImg);
imshow("PROVA",frame);
waitKey(0);
}
//chiusura e pulizia della telecamera
int en = is_ExitCamera(hCam);
if (en == IS_SUCCESS){
cout<<endl<<"Camera chiusa correttamente"<<endl;
}
is_freezeVideo is the function that doing snapshot (reading manual) but I don't understand why pictures are RED and how use in a mat file insted passing from a iplimage....
Thanks in advance to all can help me...
Hmm I tested your code on my pc and everything is working perfectly. The images are maintaining the same parameters and I get the correct outcome.
Maybe the problem is that you don't define a parameter file (.ini). In order to do it you have to define it on your own as is said in the manual and call it with the
INT is_ParameterSet(HIDS hCam, UINT nCommand, void* pParam, UINT cbSizeOfParam)
I tested it on Ubuntu 12.04, Eclipse IDE for C/C++ Developers Version: Kepler Service Release 2 with ueye Version 4.31.
Related
I made a code in c++ to take a snapshot with a Ueye camera, however the picture that gets saved is just white, in saying that sometimes to can see a tiny bit of the road but still just white. I believe it’s an issue with an auto parameter but I feel as if I have tried everything.
Below is my code:
void MainWindow::CaptureImage(){
int initcamera = is_InitCamera(&hCam, hWndDisplay);
if(initcamera != IS_SUCCESS)
{
cout<<endl<<"Failed to initialize the camera"<<endl;
exit(-1);
}else{
cout<<endl<<"Initialized Camera"<<endl;
}
int camerainfo = is_GetCameraInfo (hCam, &camera_info);
if(camerainfo != IS_SUCCESS)
{
cout<<endl<<"Unable to acquire camera information"<<endl;
exit(-1);
}else{
cout<<endl<<"Camera information required"<<endl;
}
int sensorinfo = is_GetSensorInfo (hCam, &sInfo);
if(sensorinfo != IS_SUCCESS)
{
cout<<endl<<"Unable to acquire sensor information"<<endl;
exit(-1);
}else{
cout<<endl<<"Sensor information acquired"<<endl;
}
int colormode = is_SetColorMode(hCam, IS_CM_BGR8_PACKED);
if(colormode != IS_SUCCESS)
{
cout<<endl<<"Unable to set the color mode"<<endl;
exit(-1);
}else{
cout<<endl<<"Color mode set"<<endl;
}
int pXPos = (sInfo.nMaxWidth);
int pYPos = (sInfo.nMaxHeight);
int rit = is_AllocImageMem (hCam,pXPos,pYPos, 24, &m_pcImageMemory, &m_lMemoryId);
if(rit != IS_SUCCESS)
{
cout<<endl<<"UNABLE TO INITIALIZE MEMORY"<<endl;
system("PAUSE");
exit(-1);
}else{
cout<<endl<<"INITIALIZED MEMORY"<<endl;
}
int rat = is_SetImageMem (hCam, m_pcImageMemory, m_lMemoryId);
if(rat != IS_SUCCESS)
{
cout<<endl<<"UNABLE TO ACTIVATE MEMORY"<<endl;
system("PAUSE");
exit(-1);
}else{
cout<<endl<<"ACTIVATE MEMORY"<<endl;
}
double strenght_factor = 1.0;
int colorcorrection = is_SetColorCorrection(hCam, IS_CCOR_ENABLE, &strenght_factor);
double pval = 1;
int whiteb = is_SetAutoParameter(hCam, IS_SET_ENABLE_AUTO_WHITEBALANCE, &pval, 0);
double gval = 1;
int gains = is_SetAutoParameter(hCam, IS_SET_ENABLE_AUTO_GAIN, &gval, 0);
int dummy;
char *pMem, *pLast;
IMAGE_FILE_PARAMS ImageFileParams;
ImageFileParams.pwchFileName = L"./TestImage.bmp"; /// <-- Insert name and location of the image
ImageFileParams.pnImageID = NULL;
ImageFileParams.ppcImageMem = NULL;
ImageFileParams.nQuality = 0;
ImageFileParams.nFileType = IS_IMG_BMP;
int sho = is_FreezeVideo(hCam, IS_WAIT);
if(sho != IS_SUCCESS)
{
cout<<endl<<"UNABLE TO ACQUIRE FROM THE CAMERA"<<endl;
system("PAUSE");
exit(-1);
}
if (sho == IS_SUCCESS){
int m_Ret = is_GetActiveImageMem(hCam, &pLast, &dummy);
int n_Ret = is_GetImageMem(hCam, (void**)&pLast);
}
if (is_ImageFile(hCam, IS_IMAGE_FILE_CMD_SAVE, (void*)&ImageFileParams, sizeof(ImageFileParams)) == IS_SUCCESS)
{
cout << endl << "An Image was saved" << endl;
}
else
{
cout << endl << "something went wrong" << endl;
}
// Releases an image memory that was allocated
//is_FreeImageMem(hCam, pcImageMemory, nMemoryId);
// Disables the hCam camera handle and releases the data structures and memory areas taken up by the uEye camera
is_ExitCamera(hCam);
}
I have tried many things like the parameters below however it is still just white. I had the camera in the room which is darker and the image came out ok, so I defiantly think it’s due to the day light outside.
const wstring filenameU(filename.begin(), filename.end());
is_ParameterSet(hCam, IS_PARAMETERSET_CMD_LOAD_FILE,(void*) filenameU.c_str(), 0);
unsigned int range[3];
memset(range, 0, sizeof(range));
is_PixelClock(hCam, IS_PIXELCLOCK_CMD_GET_RANGE, (void*)range, sizeof(range));
unsigned int maximumPixelClock = range[1];
is_PixelClock(hCam, IS_PIXELCLOCK_CMD_SET, (void*)&maximumPixelClock, sizeof(maximumPixelClock));
double pval1 = auto_exposure, pval2 = 0;
double pval1 = 1, pval2 = 0;
is_SetAutoParameter(hCam, IS_SET_ENABLE_AUTO_SENSOR_SHUTTER, &pval1, &pval2);
is_SetAutoParameter(hCam, IS_SET_ENABLE_AUTO_SHUTTER,&pval1, &pval2);
is_SetAutoParameter(hCam, IS_SET_ENABLE_AUTO_SENSOR_FRAMERATE,&pval1, &pval2);
is_SetAutoParameter(hCam, IS_SET_AUTO_WB_OFFSET, &pval1, &pval2);
int desiredFrameRate = 60;
is_SetFrameRate(hCam, desiredFrameRate, &m_actualFrameRate);
You cannot just take one picture because the exposure might be to high. You have to capture a few images to give the auto exposure control a chance to lower the exposure. The reason you have to capture some frames is that the AEC is done in software and can only start to change parameters if it gets some frames.
I've researched a lot for this problem, but I can´t find what exactly is causing the error.
I'm using VS 2017 and this is my header file
#ifndef FUNCTION_H
#define FUNCTION_H
#include <iostream>
#include <vector>
#include <map>
extern "C" {
#include "extApi.h"
}
void BufferToMatrix(simxUChar* buffer, unsigned int** matrix, int dim_fil, int dim_col);
void PrintMatrix(unsigned int** matriz, int dim_fil, int dim_col);
class Graph
{
// representacion por Adjacency List
std::vector<std::vector<int>> graph;
std::map<int, std::vector<int>> neighbors; // Los nodos posibles, orden izquierda, abajo, derecha, arriba
public:
// Constructores crean el numero de nodos basados en una matriz
Graph(unsigned int**, int, int);
~Graph();
};
#endif
and the .cpp file
#include <iostream>
#include <vector>
#include <map>
extern "C" {
#include "extApi.h"
}
using namespace std;
void BufferToMatrix(simxUChar* buffer, unsigned int** matrix, int dim_fil, int dim_col)
{
// Sacamos la data del buffer, dim_fil = res[1] y dim_col = res[0]
for (int i = 0; i < dim_fil; i++) // filas
{
for (int j = 0; j < dim_col; j++) // Columnas
{
matrix[j][dim_fil-1 - i] = buffer[i*dim_col + j]; // Matriz con las filas invertidas... el buffer lo entrega asi.
}
}
}
void PrintMatrix(unsigned int** matriz, int dim_fil, int dim_col)
{
// Imprimimos la matriz en consola
for (int i = 0; i < dim_fil; i++) // filas
{
for (int j = 0; j < dim_col; j++) // columnas
{
cout << matriz[j][i] << " ";
}
cout << endl;
}
}
Graph::Graph(unsigned int** map, int dim_fil, int dim_col) {}
Graph::~Graph() {}
and the main so far
#include <iostream>
#include "function.h"
#include "function.cpp"
extern "C" {
#include "extApi.h"
}
using namespace std;
int main(int argc, char* argv[])
{
// Obtenemos los Handlers enviandos en la llamada del ejecutable
int portNb = 0;
int mappingSensorHandle = 0;
//int leftMotorHandle = 0;
//int rightMotorHandle = 0;
//int graphHandle = 0;
//int proximitySensorHandle = 0;
if (argc >= 3)
{
portNb = atoi(argv[1]);
mappingSensorHandle = atoi(argv[2]);
//leftMotorHandle = atoi(argv[3]);
//rightMotorHandle = atoi(argv[4]);
//graphHandle = atoi(argv[5]);
//proximitySensorHandle = atoi(argv[6]);
}
else
{
cout << "Es necesario indicar los handlers en V-rep" << endl;
extApi_sleepMs(5000);
return 0;
}
// Iniciamos la simulacion
int clientID = simxStart((simxChar*)"127.0.0.1", portNb, true, true, 2000, 5);
if (clientID != -1)
{
// Declaraciones de variables auxiliares
int retVal = 0;
bool OneTimeFlag = 0;
// Declaraciones de variables, lectura del mapa
simxInt res[2]; //res[0] son columnas y res[1] son filas
simxUChar* image; //apuntador al arreglo con la data del sensor de vision
simxUChar options = 1; //en 1 recibe en escala de grises, en 0 recibe en rgb
// Habilitamos el Streaming del mapa
simxGetVisionSensorImage(clientID, mappingSensorHandle, res, &image, options, simx_opmode_streaming);
OneTimeFlag = 1;
// Creamos una matriz dinamica para el mapa
unsigned int** map = new unsigned int* [res[1]];
for (int i = 0; i < res[1]; i++)
{
map[i] = new unsigned int[res[0]];
}
// Loop de la simulacion en V-rep
while (simxGetConnectionId(clientID) != -1)
{
if (OneTimeFlag)
{
retVal = simxGetVisionSensorImage(clientID, mappingSensorHandle, res, &image, options, simx_opmode_buffer);
if (retVal == simx_return_ok)
{
BufferToMatrix(image, map, res[1], res[0]); // Llenamos la matriz
PrintMatrix(map, res[1], res[0]); // Imprimimos la matriz en CMD
OneTimeFlag = 0; // Colocamos la flag en 0 para no ejecutar esta parte
}
// Creamos el grafo y el SpanningTree
//Graph grafo(map, res[1], res[0]);
}
}
// Borramos la matriz del mapa
for (int i = 0; i < res[1]; i++)
{
delete [] map[i];
}
delete [] map;
simxFinish(clientID);
}
else
{
// Terminamos la simulacion, no se realizo la conexion
cout << "Conexion no lograda" << endl;
simxFinish(clientID);
return(0);
}
return(0);
}
this is a script to use a external API in V-rep, the only lines that cause trouble is this two lines in the .h file
std::vector<std::vector<int>> graph;
std::map<int, std::vector<int>> neighbors;
Cause this problems:
Error LNK2001 símbolo externo __imp___CrtDbgReport sin resolver.
Error LNK2001 símbolo externo __imp___invalid_parameter sin resolver.
Error LNK1120 2 externos sin resolver coverageBotClient.
I apologize because this is to simple but I can´t see the error.
I writting a software for my classes that receive a h264 stream from a drone and i need to convert the video stream to opencv Mat.
I have no trouble to receive the frame and if i save it to a .264 file i can read the output with VLC.
The drone is sending IDR-Frame and P-Frame , since i don't need to see the video stream juste some frame of it, i was thinking of only using the IDR-Frame to get the image but i have trouble to understand how to use libavcodec from FFMPEG, how can i create a AVFrame from my IDR-Frame and how to convert it to cv::Mat after.
i have try the following code, i have store the full frame in .raw file and i try to decode them , but i get read error when i try to parse the packet to a frame, i don't thing a initialize the buffer of ARPacket the right way :
AVFormatContext* fc = 0;
int vi = -1; // vi veut dire video index
inline cv::Mat avframe_to_mat(const AVFrame* avframe)
{
AVFrame dst;
cv::Mat m;
memset(&dst, 0, sizeof(dst));
int w = avframe->width, h = avframe->height;
m = cv::Mat(h, w, CV_8UC3);
dst.data[0] = (uint8_t*)m.data;
avpicture_fill((AVPicture*)&dst, dst.data[0], AV_PIX_FMT_BGR24, w, h);
struct SwsContext *convert_ctx = NULL;
enum AVPixelFormat src_pixfmt = AV_PIX_FMT_BGR24;
enum AVPixelFormat dst_pixfmt = AV_PIX_FMT_BGR24;
convert_ctx = sws_getContext(w, h, src_pixfmt, w, h, dst_pixfmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);
sws_scale(convert_ctx, avframe->data, avframe->linesize, 0, h, dst.data, dst.linesize);
sws_freeContext(convert_ctx);
return m;
}
inline bool init_stream(unsigned char* data, int len)
{
const char* file = "test.avi";
const AVCodecID codec_id = AV_CODEC_ID_H264;
AVCodec* codec = avcodec_find_encoder(codec_id);
// Crée le container pour le stream
fc = avformat_alloc_context();
/*
AVOutputFormat *of = av_guess_format(0, file, 0);
fc = avformat_alloc_context();
fc->oformat = of;
strcpy(fc->filename, file);
*/
int br = 1000000;
int w = 640;
int h = 360;
int fps = 24;
// ajoute un stream video
AVStream* pst = avformat_new_stream(fc, codec); // Pourquoi je passe pas le codec ici ?
vi = pst->index;
codec_context = avcodec_alloc_context3(codec);
codec_context->bit_rate = br;
codec_context->width = w;
codec_context->height = h;
codec_context->time_base = {1,fps};
codec_context->gop_size = 10; // Emit one intra frame every ten frames
codec_context->max_b_frames = 1;
codec_context->pix_fmt = AV_PIX_FMT_YUV420P;
// Vu quon n'est en h264
av_opt_set(codec_context->priv_data, "preset", "slow", 0);
// Ouvre notre codec
if(avcodec_open2(codec_context, codec,nullptr) < 0)
{
cerr << "Impossible d'ouvrir le codec" << endl;
return false;
}
if (!(fc->oformat->flags & AVFMT_NOFILE))
avio_open(&fc->pb, fc->filename,0);
// avformat_write_header(fc,nullptr);
return true;
}
inline void append_stream(uint8_t* data, int len)
{
if( 0 > vi)
{
cerr << "video index is less than 0" << endl;
return;
}
AVStream* pst = fc->streams[vi];
AVPacket pkt;
// Init un nouveau packet
av_init_packet(&pkt);
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.data = data;
pkt.stream_index = pst->index;
pkt.size = len;
pkt.dts = AV_NOPTS_VALUE;
pkt.pts = AV_NOPTS_VALUE;
// ERROR accessing location
av_interleaved_write_frame(fc, &pkt);
}
inline void execute_staging_test(const fs::path& folder, int nbr_trame)
{
fs::path file_name = folder / "stream.bin";
if(!fs::exists(file_name))
{
cerr << "The file " << file_name.string() << " does not exists" << endl;
return;
}
avcodec_register_all();
av_log_set_level(AV_LOG_DEBUG);
int length = 0;
char* buffer;
for(int i = 0; i < nbr_trame;i++)
{
fs::path file = std::to_string(i) + ".raw";
file = folder / file;
cout << "Got frame on " << file.string() << endl;
ifstream ifs(file, ofstream::binary);
// Get la longeur du fichier pour savoir le buffer a prendre
ifs.seekg(0, ios::end);
length = ifs.tellg();
ifs.seekg(0, ios::beg);
if (length == 0) {
std::cerr << "No data in file " << file << std::endl;
return;
}
buffer = new char[length];
std::cout << "File " << file << " length is " << length << std::endl;
ifs.read(buffer, length);
cv::VideoWriter vw;
int codec = cv::VideoWriter::fourcc('X', '2', '6', '4');
if(!fc)
{
if(!init_stream((unsigned char*)buffer, length))
{
return;
}
}
if(fc)
{
append_stream((unsigned char*)buffer, length);
}
}
}
Thanks you very mutch if you can help me , i'm a novice in c++ and i have never deal with video stream. If you want to see the full code its host on github repo to this project
I have done a DNI text recognition project using Visual Studio, the OpenCV library and the KNN recognition method.
To simplify the project I cut the fields whose information I want to extract and I did the whole process to each of them, obtaining good results.
But I have noticed that the program confuses an M with N and also classifies O as 0.
How could I fix it?
I will show you the field where detection incorrect occurs.
CODE:
#include <iostream>
#include <vector>
#include <opencv2\opencv.hpp>
#include <opencv2\highgui/highgui.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\ml\ml.hpp>
#include "Preproceso.h"
// VARIABLES GLOBALES
/////////////////////////////////////////////////////
const int AREA_MINIMA_DE_CONTORNO = 70;
const int ANCHO_IMAGEN_REDIM = 20;
const int ALTURA_IMAGEN_REDIM = 30;
class ContornoConDatos {
public:
// variables miembro
///////////////////////////////////////////////////////////////////////////
std::vector<cv::Point> ptContorno;
cv::Rect rectanguloDelimitador;
float fltAreaDelContorno;
////////////////////////////////////////////////////////////////////////////
bool comprobarSiContornoValido() {
if (fltAreaDelContorno < AREA_MINIMA_DE_CONTORNO) return false;
return true;
}
////////////////////////////////////////////////////////////////////////////
static bool ordenarPosicionXRectDelim(const ContornoConDatos& ccdIzquierda, const ContornoConDatos& ccdDerecha) {
return(ccdIzquierda.rectanguloDelimitador.x < ccdDerecha.rectanguloDelimitador.x);
}
};
//////////////////////////////////////////////////////////////////
void preprocess(cv::Mat &imagenOriginal, cv::Mat &imagenEscalaDeGrises, cv::Mat &imagenUmbralizada) {
imagenEscalaDeGrises = extraerValor(imagenOriginal);
cv::Mat imagenMaxContrasteEscalaDeGrises = maximizarContraste(imagenEscalaDeGrises);
cv::Mat imagenSuavizada;
cv::GaussianBlur(imagenMaxContrasteEscalaDeGrises, imagenSuavizada, TAMAÑO_FILTRO_SUAVE_GAUSSIANO, 0);
cv::adaptiveThreshold(imagenSuavizada, imagenUmbralizada, 255.0, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, TAMAÑO_BLOQUE_UMBRAL, ANCHO_UMBRAL);
}
///////////////////////////////////////////////////////////////////
cv::Mat extraerValor(cv::Mat &imagenOriginal) {
cv::Mat imagenHSV;
std::vector<cv::Mat> vectorDeImagenesHSV(2);
cv::Mat imagenValor;
cv::cvtColor(imagenOriginal, imagenHSV, CV_BGR2HSV);
cv::split(imagenHSV, vectorDeImagenesHSV);
imagenValor = vectorDeImagenesHSV[2];
return(imagenValor);
}
//////////////////////////////////////////////////////////////
cv::Mat maximizarContraste(cv::Mat &imagenEscalaDeGrises) {
cv::Mat imagenTopHat;
cv::Mat imagenBlackHat;
cv::Mat imagenEscalaDeGrisesMasTopHat;
cv::Mat imagenEscalaDeGrisesMasTopHatMenosBlackHat;
cv::Mat structuringElement = cv::getStructuringElement(CV_SHAPE_RECT, cv::Size(3, 3));
cv::morphologyEx(imagenEscalaDeGrises, imagenTopHat, CV_MOP_TOPHAT, structuringElement);
cv::morphologyEx(imagenEscalaDeGrises, imagenBlackHat, CV_MOP_BLACKHAT, structuringElement);
imagenEscalaDeGrisesMasTopHat = imagenEscalaDeGrises + imagenTopHat;
imagenEscalaDeGrisesMasTopHatMenosBlackHat = imagenEscalaDeGrisesMasTopHat - imagenBlackHat;
return(imagenEscalaDeGrisesMasTopHatMenosBlackHat);
}
//////////////////////////////////////////////////////
int main()
{
cv::Ptr<cv::ml::KNearest> kNearest(cv::ml::KNearest::create());
// read in training classifications ///////////////////////////////////////////////////
cv::Mat matrizClasificacionCaracteres;
cv::FileStorage archivoClasificacion("classifications.xml", cv::FileStorage::READ);
if (archivoClasificacion.isOpened() == false) {
std::cout << "error, unable to open training classifications file, exiting program\n\n";
return(0);
}
archivoClasificacion["classifications"] >> matrizClasificacionCaracteres;
archivoClasificacion.release();
// read in training images ////////////////////////////////////////////////////////////
cv::Mat matrizPixelesImagenReferencia;
cv::FileStorage archivoImagenes("images.xml", cv::FileStorage::READ);
if (archivoImagenes.isOpened() == false) {
std::cout << "error, unable to open training images file, exiting program\n\n";
return(0);
}
archivoImagenes["images"] >> matrizPixelesImagenReferencia;
archivoImagenes.release();
////////////////////////////////////////////////////////////////
//entrenamiento
//cv::Ptr<cv::ml::KNearest> kNearest(cv::ml::KNearest::create());
kNearest->setDefaultK(1);
kNearest->train(matrizPixelesImagenReferencia, cv::ml::ROW_SAMPLE, matrizClasificacionCaracteres);
//Leer la imagen base, de la cual obtengo solamente las dimensiones para asignarselas a mi verdadera imagen, con la que voy a trabajar
cv::Mat imagenBase = cv::imread("ImagenBase.png");
if (imagenBase.empty()) {
std::cout << "No se puede leer la imagen del archivo \n\n";
return (0);
}
////////////////////////////////////////////////////////////////
//Leer la imagen con la que voy a trabajar, a la cual le realizo el cambio de dimension
cv::Mat imagenOriginal = cv::imread("DNI-Jessica.jpg");
//cv::Mat imagenOriginal = cv::imread("DNI.png");
if (imagenOriginal.empty()) {
std::cout << "No se puede leer la imagen del archivo \n\n";
return (0);
}
// Redimensionar imagenOriginal al tamaño de imagenBase para que todas las imagenes de entrada tengan las mismas dimensiones
cv::resize(imagenOriginal, imagenOriginal, imagenBase.size());
cv::imshow("ImagenOriginal", imagenOriginal);
//Sección de interés 2: SEGUNDO APELLIDO///////////////////////////////
cv::Rect dimensionesROI2(255, 128, 300, 30);
//cv::Rect dimensionesROI2(250, 125, 300, 30);
//Recortar la imagen original para obtener ROI2
cv::Mat ROI2 = imagenOriginal(dimensionesROI2);
//PRE-PROCESADO DE LA IMAGEN/////////////////////////////////////////////
cv::Mat imagenEscalaDeGrises2;
cv::Mat imagenSuavizada2;
cv::Mat imagenUmbralizada2;
preprocess(ROI2, imagenSuavizada2, imagenUmbralizada2);
cv::threshold(imagenUmbralizada2, imagenUmbralizada2, 0.0, 255.0, CV_THRESH_BINARY | CV_THRESH_OTSU);
cv::Mat imagenDeTrabajo2 = imagenUmbralizada2.clone();
cv::imshow("Imagen pre-procesada 2", imagenUmbralizada2);
////////////////////////////////////////////////////////
std::vector<ContornoConDatos> todosLosContornos2;
std::vector<ContornoConDatos> contornosValidos2;
std::vector<std::vector<cv::Point> > ptContornos2;
std::vector<cv::Vec4i> v4iJerarquia2;
cv::findContours(imagenDeTrabajo2, ptContornos2, v4iJerarquia2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
for (int i = 0; i < ptContornos2.size(); i++)
{
ContornoConDatos contornoConDatos2;
contornoConDatos2.ptContorno = ptContornos2[i];
contornoConDatos2.rectanguloDelimitador = cv::boundingRect(contornoConDatos2.ptContorno);
contornoConDatos2.fltAreaDelContorno = cv::contourArea(contornoConDatos2.ptContorno);
todosLosContornos2.push_back(contornoConDatos2);
}
for (int i = 0; i < todosLosContornos2.size(); i++)
{
if (todosLosContornos2[i].comprobarSiContornoValido())
{
contornosValidos2.push_back(todosLosContornos2[i]);
}
}
std::sort(contornosValidos2.begin(), contornosValidos2.end(), ContornoConDatos::ordenarPosicionXRectDelim);
std::string strCadenaFinal2;
for (int i = 0; i < contornosValidos2.size(); i++)
{
cv::rectangle(ROI2, contornosValidos2[i].rectanguloDelimitador, cv::Scalar(0, 255, 0), 2);
cv::Mat imagenROI2 = imagenUmbralizada2(contornosValidos2[i].rectanguloDelimitador);
cv::Mat imagenROIRedimensionada2;
cv::resize(imagenROI2, imagenROIRedimensionada2, cv::Size(ANCHO_IMAGEN_REDIM, ALTURA_IMAGEN_REDIM));
cv::Mat matrizROIDatosTipoReal2;
imagenROIRedimensionada2.convertTo(matrizROIDatosTipoReal2, CV_32FC1);
cv::Mat matrizROIConRealesSimples2 = matrizROIDatosTipoReal2.reshape(1, 1);
cv::Mat vectorCaracterActual2(0, 0, CV_32F);
kNearest->findNearest(matrizROIConRealesSimples2, 1, vectorCaracterActual2);
float fltCaracterActual2 = (float)vectorCaracterActual2.at<float>(0, 0);
strCadenaFinal2 = strCadenaFinal2 + char(int(fltCaracterActual2));
}
std::cout << "\n" << "SEGUNDO APELLIDO = " << strCadenaFinal2 << "\n";
cv::imshow("SEGUNDO APELLIDO", ROI2);
Preproceso.h CODE:
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
// global variables
//////////////////////////////////////////////
const cv::Size TAMAÑO_FILTRO_SUAVE_GAUSSIANO = cv::Size(5, 5);
const int TAMAÑO_BLOQUE_UMBRAL = 19;
const int ANCHO_UMBRAL = 9;
// function prototypes
////////////////////////////////////////////////////////////////////////////
void preprocess(cv::Mat &imagenOriginal, cv::Mat &imagenEscalaDeGrises,
cv::Mat &imagenUmbralizada);
cv::Mat extraerValor(cv::Mat &imagenOriginal);
cv::Mat maximizarContraste(cv::Mat &imagenEscalaDeGrises);
This is the DNI image
And this, the base image
And to finish, here are the xml files that I use as a database in the program:
https://github.com/MicrocontrollersAndMore/OpenCV_3_KNN_Character_Recognition_Cpp/blob/master/classifications.xml
https://github.com/MicrocontrollersAndMore/OpenCV_3_KNN_Character_Recognition_Cpp/blob/master/images.xml
I'm kinda new in asking #Stackoverflow, however it's been the closest thing I have as a Bible (other than Ritchie's C book) specially in these days of final projects for most of my subjects. Anyway, my question is about the libraries needed for an application that communicates with a HID Device and the possibility to do it with C++.
I don't need help with the Firmware, my device is already working the way I expect it to. However my only experience programming HID devices is with C (Windows - VS2010) and right now I am in a final project for Compilers class in wich we send information to a device with a matrix screen to display "stuff". My partner however needs to do something in C++ which can save us a lot of time (something nice considering its due in two days).
The whole point of this being to ask if it can be done the same way that I already have in C (with its obvious adjustments) and some parts of the code in C++ and still get to be compatible with SetupApi.DLL and HID.DLL
Any kind of advice, pointers or instructions is deeply appreciated. I include the code I have used so far.
Excuse all the comments in spanish and mess I might have
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <windows.h>
#include <SETUPAPI.H>
//----------------------------------------------
#define RICH_VENDOR_ID 0x0000
#define RICH_USBHID_GENIO_ID 0x2012
#define INPUT_REPORT_SIZE 5
#define OUTPUT_REPORT_SIZE 2
//----------------------------------------------
char c=0x0;
DWORD BytesRead = 0;
DWORD BytesWritten = 0;
unsigned char reporteEntrada[INPUT_REPORT_SIZE+1];
unsigned char reporteSalida[OUTPUT_REPORT_SIZE+1];
int status = 0;
static unsigned char dato = 0x01;
static unsigned char numLED = 1;
unsigned char palabra[192]={0};
int desplegar,valorled;
desplegar=0;
valorled=0;
unsigned char temporal;
//unsigned char ch;
//unsigned int index;
typedef struct _HIDD_ATTRIBUTES {
ULONG Size; // = sizeof (struct _HIDD_ATTRIBUTES)
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
typedef VOID (__stdcall *PHidD_GetProductString)(HANDLE, PVOID, ULONG);
typedef VOID (__stdcall *PHidD_GetHidGuid)(LPGUID);
typedef BOOLEAN (__stdcall *PHidD_GetAttributes)(HANDLE, PHIDD_ATTRIBUTES);
typedef BOOLEAN (__stdcall *PHidD_SetFeature)(HANDLE, PVOID, ULONG);
typedef BOOLEAN (__stdcall *PHidD_GetFeature)(HANDLE, PVOID, ULONG);
//----------------------------------------------
HINSTANCE hHID = NULL;
PHidD_GetProductString HidD_GetProductString = NULL;
PHidD_GetHidGuid HidD_GetHidGuid = NULL;
PHidD_GetAttributes HidD_GetAttributes = NULL;
PHidD_SetFeature HidD_SetFeature = NULL;
PHidD_GetFeature HidD_GetFeature = NULL;
HANDLE DeviceHandle = INVALID_HANDLE_VALUE;
unsigned int moreHIDDevices=TRUE;
unsigned int HIDDeviceFound=FALSE;
unsigned int terminaAbruptaEInstantaneamenteElPrograma=0;
void Load_HID_Library (void) {
hHID = LoadLibrary("HID.DLL");
if (!hHID) {
printf("Failed to load HID.DLL\n");
return;
}
HidD_GetProductString = (PHidD_GetProductString) GetProcAddress(hHID, "HidD_GetProductString");
HidD_GetHidGuid = (PHidD_GetHidGuid) GetProcAddress(hHID, "HidD_GetHidGuid");
HidD_GetAttributes = (PHidD_GetAttributes) GetProcAddress(hHID, "HidD_GetAttributes");
HidD_SetFeature = (PHidD_SetFeature) GetProcAddress(hHID, "HidD_SetFeature");
HidD_GetFeature = (PHidD_GetFeature) GetProcAddress(hHID, "HidD_GetFeature");
if ( !HidD_GetProductString
|| !HidD_GetAttributes
|| !HidD_GetHidGuid
|| !HidD_SetFeature
|| !HidD_GetFeature ) {
printf("Couldn't find one or more HID entry points\n");
return;
}
}
int Open_Device(void) {
HDEVINFO DeviceInfoSet;
GUID InterfaceClassGuid;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData;
HIDD_ATTRIBUTES Attributes;
DWORD Result;
DWORD MemberIndex = 0;
DWORD Required;
//Validar si se "cargó" la biblioteca (DLL)
if (!hHID)
return (0);
//Obtener el Globally Unique Identifier (GUID) para dispositivos HID
HidD_GetHidGuid (&InterfaceClassGuid);
//Sacarle a Windows la información sobre todos los dispositivos HID instalados y activos en el sistema
// ... almacenar esta información en una estructura de datos de tipo HDEVINFO
DeviceInfoSet = SetupDiGetClassDevs(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
if (DeviceInfoSet == INVALID_HANDLE_VALUE)
return (0);
//Obtener la interfaz de comunicación con cada uno de los dispositivos para preguntarles información específica
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
while (!HIDDeviceFound) {
// ... utilizando la variable MemberIndex ir preguntando dispositivo por dispositivo ...
moreHIDDevices = SetupDiEnumDeviceInterfaces (DeviceInfoSet, NULL, &InterfaceClassGuid,
MemberIndex,&DeviceInterfaceData);
if (!moreHIDDevices) {
// ... si llegamos al fin de la lista y no encontramos al dispositivo ==> terminar y marcar error
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return (0); //No more devices found
} else {
//Necesitamos preguntar, a través de la interfaz, el PATH del dispositivo, para eso ...
// ... primero vamos a ver cuántos caracteres se requieren (Required)
Result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet,&DeviceInterfaceData,NULL,0,&Required,NULL);
pDeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Required);
if (pDeviceInterfaceDetailData == NULL) {
printf("Error en SetupDiGetDeviceInterfaceDetail\n");
return (0);
}
//Ahora si, ya que el "buffer" fue preparado (pDeviceInterfaceDetailData{DevicePath}), vamos a preguntar PATH
pDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
Result = SetupDiGetDeviceInterfaceDetail (DeviceInfoSet,&DeviceInterfaceData,pDeviceInterfaceDetailData,
Required,NULL,NULL);
if (!Result) {
printf("Error en SetupDiGetDeviceInterfaceDetail\n");
free(pDeviceInterfaceDetailData);
return(0);
}
//Para este momento ya sabemos el PATH del dispositivo, ahora hay que preguntarle ...
// ... su VID y PID, para ver si es con quien nos interesa comunicarnos
printf("Found? ==> ");
printf("Device: %s\n",pDeviceInterfaceDetailData->DevicePath);
//Obtener un "handle" al dispositivo
DeviceHandle = CreateFile (pDeviceInterfaceDetailData->DevicePath,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
0,
NULL);
if (DeviceHandle == INVALID_HANDLE_VALUE) {
printf("¡¡¡Error en el CreateFile!!!\n");
} else {
//Preguntar por los atributos del dispositivo
Attributes.Size = sizeof(Attributes);
Result = HidD_GetAttributes (DeviceHandle,&Attributes);
if (!Result) {
printf("Error en HIdD_GetAttributes\n");
CloseHandle(DeviceHandle);
free(pDeviceInterfaceDetailData);
return(0);
}
//Analizar los atributos del dispositivo para verificar el VID y PID
printf("MemberIndex=%d,VID=%04x,PID=%04x\n",MemberIndex,Attributes.VendorID,Attributes.ProductID);
if ((Attributes.VendorID == RICH_VENDOR_ID) && (Attributes.ProductID == RICH_USBHID_GENIO_ID)) {
printf("USB/HID GenIO ==> ");
printf("Device: %s\n",pDeviceInterfaceDetailData->DevicePath);
HIDDeviceFound=TRUE;
} else
CloseHandle(DeviceHandle);
}
MemberIndex++;
free(pDeviceInterfaceDetailData);
if (HIDDeviceFound) {
printf("Dispositivo HID solicitado ... ¡¡¡localizado!!!, presione <ENTER>\n");
getchar();
}
}
}
return(1);
}
void Close_Device (void) {
if (DeviceHandle != NULL) {
CloseHandle(DeviceHandle);
DeviceHandle = NULL;
}
}
int chToIndex(unsigned char ch){
if((ch>='0')&&(ch<='9')){
return ch-48;
}else if((ch>='A')&&(ch<='Z')){
return ch-55;
}else if((ch>='a')&&(ch<='z')){
return ch-61;
}else{
switch (ch){
case '*': return 62;
// break;
case '+': return 63;
// break;
case '-': return 64;
//break;
case '/': return 65;
//break;
case '=': return 66;
// break;
case '>': return 67;
// break;
case '<': return 68;
// break;
case '!': return 69;
// break;
case '.': return 70;
// break;
case '&': return 71;
// break;
case '^': return 72;
// break;
case '(': return 73;
// break;
case ')': return 74;
// break;
case '[': return 75;
// break;
case ']': return 76;
// break;
case ',': return 77;
// break;
case ';': return 78;
// break;
case ':': return 79;
// break;
case 0x20: return 80;
default: return 81;
// break;
}
}
}
int Touch_Device (void) {
int z;
int index;
int col,lin;
unsigned char ch;
if (DeviceHandle == NULL) //Validar que haya comunicacion con el dispositivo
return 0;
if(c != '27' )
{
printf("Selecciona accion:\n1) Limpiar Pantalla\n2) Imprimir todos caracteres\n3) Escribir caracter\n4) Escribir string\n5) Salir\n");
desplegar=getch();
desplegar=getch();
if((desplegar=='5')||(desplegar==(char)'27')){
terminaAbruptaEInstantaneamenteElPrograma=1;
}
else if(desplegar=='4'){
lin=0;
col=0;
index=0;
printf("Escribe texto (termina con Enter):\n");
scanf("%s",palabra);
while(palabra[index]!='\0'){
z++;
}
printf("Longitud de palabra: %d",z);
while((palabra[index]!='\0')){
if((palabra[index]==NULL)&&(palabra[index+1]!=NULL))
palabra[index]=0x20;
reporteSalida[0]=0x00;
reporteSalida[1]=0x04;
reporteSalida[2]=(char)chToIndex(palabra[index]);
reporteSalida[3]=(char)lin;
reporteSalida[4]=(char)col;
status = WriteFile(DeviceHandle,reporteSalida,INPUT_REPORT_SIZE+1,&BytesWritten,NULL);
if (!status)
printf("Error en el WriteFile %d %d\n",GetLastError(),BytesWritten);
else
printf("Se enviaron %d bytes al dispositivo (posX=%d, posY=%d, dato=%d)\n",BytesWritten,reporteSalida[4],reporteSalida[3],reporteSalida[2]);
if(col>=23){
lin++;
col=0;
}
if(lin>=7){
lin=0;
}
col++;
index++;
}
}
else if (desplegar=='3'){
reporteSalida[0]=0x00;
reporteSalida[1]=0x04;
printf("Que caracter deseas desplegar: ");
ch=getch();
printf("\n");
z=chToIndex(ch);
reporteSalida[2]=(char)z;
do{
printf("En que renglon en y (0-7): ");
scanf("%d",&desplegar);
printf("\n");
}while((desplegar<0)&&(desplegar>7));
reporteSalida[3]=(char)desplegar;
do{
printf("En que columna en x (0-23): ");
scanf("%d",&desplegar);
printf("\n");
}while((desplegar<0)&&(desplegar>23));
reporteSalida[4]=(char)desplegar;
printf("ReporteSalida: %02X %02X %02X %02X %02X \n",(unsigned char)reporteSalida[0],
(unsigned char)reporteSalida[1],
(unsigned char)reporteSalida[2],
(unsigned char)reporteSalida[3],
(unsigned char)reporteSalida[4]);
status = WriteFile(DeviceHandle,reporteSalida,INPUT_REPORT_SIZE+1,&BytesWritten,NULL);
if (!status)
printf("Error en el WriteFile %d %d\n",GetLastError(),BytesWritten);
else
printf("Se enviaron %d bytes al dispositivo (posX=%d, posY=%d, dato=%d)\n",BytesWritten,reporteSalida[4],reporteSalida[3],reporteSalida[2]);
}
else if (desplegar=='2'){
lin=0;
col=0;
for (index=0;index<=80;index++){
reporteSalida[0]=0x00;
reporteSalida[1]=0x04;
reporteSalida[2]=(char)index;
reporteSalida[3]=(char)lin;
reporteSalida[4]=(char)col;
status = WriteFile(DeviceHandle,reporteSalida,INPUT_REPORT_SIZE+1,&BytesWritten,NULL);
if (!status)
printf("Error en el WriteFile %d %d\n",GetLastError(),BytesWritten);
else
printf("Se enviaron %d bytes al dispositivo (posX=%d, posY=%d, dato=%d)\n",BytesWritten,reporteSalida[4],reporteSalida[3],reporteSalida[2]);
if(col>=23){
lin++;
col=0;
}
if(lin>=7){
lin=0;
}
col++;
}
}
else if(desplegar=='1'){
printf("Limpiando pantalla ...\n");
reporteSalida[0]=0x00;
reporteSalida[1]=0x03;
reporteSalida[2]=0;
status = WriteFile(DeviceHandle,reporteSalida,INPUT_REPORT_SIZE+1,&BytesWritten,NULL);
if (!status)
printf("Error en el WriteFile %d %d\n",GetLastError(),BytesWritten);
else
printf("Escritos %d\n",BytesWritten);
}
else{
Touch_Device();
}
}
return status;
}
void main () {
Load_HID_Library();
if (Open_Device()) {
printf("Vamos bien\n");
while ((c=getch()!=27)
&&(!terminaAbruptaEInstantaneamenteElPrograma)) {
Touch_Device();
Sleep(500);
}
} else {
printf(">:(\n");
}
Close_Device();
}
By and large, you can compile any C code as C++. Have you tried to compile it as C++ and did you get any errors?
The answer to your question is that, yes, you can use SETUPAPI.DLL and HID.DLL from C++ exactly as you would with C.
Change your C source file into C++. If you are using VS, it could be as easy as change the file extension (.c -> .cpp) and fix some warning issues.
C++ programs can use setupapi.dll (C library) because APIs are declared like below.
(In the header file)
#ifdef __cplusplus
extern "C" {
#endif
int declaration_of_c_function(...);
#ifdef __cplusplus
}
#endif
extern "C" is the new syntax introduced in C++ to enable C/C++ integration.
That is, it not simple if you don't know C++.