Comment / Pourquoi les images stockées sont-elles stockées sous la forme d’un caractère – OpenCV

Je suis un peu confus.

Je commence tout juste à utiliser OpenCV et ses données d’image sont pointées par un pointeur de caractère. Je ne peux pas vraiment comprendre comment cela fonctionne, étant donné que les données elles-mêmes pourraient être constituées de plusieurs types de données, par exemple uint, float, double. Autant que je sache, un pointeur devait être du même type que le pointeur qu’il représente.

Il est probablement intéressant de noter qu’openCV est une bibliothèque C et que mon expérience est C ++, je ne suis donc pas au courant de la façon dont ces problèmes de besoin de types de variable sont résolus dans C.

Par exemple, le code suivant tiré de Learning OpenCV illustre ma confusion:

void saturate_sv( IplImage* img ) { for( int y=0; yheight; y++ ) { uchar* ptr = (uchar*) ( img->imageData + y * img->widthStep ); for( int x=0; xwidth; x++ ) { ptr[3*x+1] = 255; ptr[3*x+2] = 255; } } } 

Donc, cela fonctionne, mais lorsque j’essaie de fonctionner sur un iplImage de type IPL_DEPTH_64F et d’utiliser ptr [3 * x + 1] = 1, les résultats sont incorrects. Donc, pour résumer mes problèmes: comment puis-je travailler sur des données à nombres entiers ou à virgule flottante par le biais de pointeurs de caractères et précisément comment rectifier l’exemple ci-dessus pour utiliser des données à double précision.

Merci

  1. IPL_DEPTH_64F ou double images double s’occuperont des données de 0 à 1.
  2. Si vous êtes habitué à C ++, vous devriez essayer OpenCV2.0 qui contient plusieurs classes C ++ et, surtout, une classe, c’est-à-dire Mat pour gérer les images, les masortingces, etc.

Voici un moyen simple d’accéder efficacement aux éléments de votre image:

 IplImage* img = cvCreateImage(cvSize(300,300),IPL_DEPTH_64F,1); for( int y=0; yheight; y++ ) { double* ptr = reinterpret_cast(img->imageData + y * img->widthStep); for( int x=0; xwidth; x++ ) { ptr[x] = double(255); } } cvNamedWindow("SO"); cvShowImage("SO",img); cvWaitKey(); cvDestroyAllWindows(); cvReleaseImage(&img); 

Puisque vous travaillez avec une image double , il est plus logique de:

  1. Travaillez avec un double pointeur pour pouvoir facilement assigner des éléments dans une ligne avec ptr[x]
  2. Faire l’arithmétique du pointeur en octets ( img->imageData + y * img->widthStep ) et le img->imageData + y * img->widthStep en un double pointeur

En outre, il est important que vous fassiez l’arithmétique de pointeur en octets (ou uchar , c’est-à-dire un caractère unsigned char ) car OpenCV a tendance à remplir les rangées d’images avec des octets supplémentaires pour plus d’efficacité (en particulier pour double images double ).

Ainsi, même si un élément double est constitué de 8 octets et que vous avez, par exemple, 300 lignes, il n’est pas garanti qu’une ligne se termine à 8 * 300 ou 2400 octets, car OpenCV pourrait remplir la fin.

Par conséquent, cela vous empêche d’initialiser un pointeur sur le premier élément de l’image, puis d’utiliser ptr[y*img->height+x] pour accéder aux éléments, car chaque ligne peut avoir plus de 8*(y*img->height) octets.

C’est pourquoi l’exemple de code calcule chaque fois le pointeur sur chaque ligne à l’aide de img->widthStep qui représente la taille réelle en octets de chaque ligne.

OpenCV 2.0

Si vous utilisez la classe Mat , vous pouvez faire la même chose dans ce sens:

 cv::Mat img(300,300,CV_64FC1); for( int y=0; y(img.data + y * img.step); for( int x=0; x 

où img.step est la distance entre les lignes successives en octets

Et si vous voulez accéder directement à l’élément (plus lent):

img.at(y,x)