web-dev-qa-db-fra.com

Quelles sont les différences entre CV_8U et CV_32F et de quoi dois-je m'inquiéter lors de la conversion entre eux?

J'ai du code qui agit et je pense que c'est parce que j'opère sur les mauvais types de données ou que je convertis mal entre eux.

Il mélange cv::Mat objets de types CV_8U (qui est créé lors de la lecture d'un jpg en niveaux de gris avec cv::imread), CV_32F, et CV_32S.

Quelles sont les différences entre ces types de données et de quoi ai-je besoin lors de la conversion entre eux?

47
mic

CV_8U n'est pas signé 8 bits/pixel - c'est-à-dire qu'un pixel peut avoir des valeurs de 0 à 255, c'est la plage normale pour la plupart des formats d'image et de vidéo.

CV_32F est flottant - le pixel peut avoir n'importe quelle valeur entre 0 et 1,0, cela est utile pour certains ensembles de calculs sur les données - mais il doit être converti en 8 bits pour enregistrer ou afficher en multipliant chaque pixel par 255.

CV_32S est une valeur entière de 32 bits signée pour chaque pixel - une fois de plus, vous êtes utile de faire des calculs entiers sur les pixels, mais vous devez à nouveau convertir en 8 bits pour enregistrer ou afficher. C'est plus délicat car vous devez décider comment convertir la plage beaucoup plus large de valeurs possibles (+/- 2 milliards!) En 0-255

86
Martin Beckett

Fondamentalement, ils décrivent simplement les composants individuels:

  • CV_8U: Entier non signé sur 1 octet (unsigned char).

  • CV_32S: Entier signé sur 4 octets (int).

  • CV_32F: Virgule flottante sur 4 octets (float).

Ce que vous devez toujours garder à l'esprit, c'est que vous ne pouvez pas simplement les convertir de l'un dans l'autre (ou il ne fera probablement pas ce que vous voulez), en particulier entre les types de tailles différentes.

Assurez-vous donc toujours d'utiliser des fonctions de conversion réelles pour convertir entre elles, comme cv::convert ou cv::Mat::convertTo. N'essayez pas simplement d'accéder aux éléments de, par ex. une cv::Mat de CV_8U tapez en utilisant par exemple cv::Mat::at<float> ou cv::Mat_<float>.

Ou si vous souhaitez simplement convertir des éléments individuels et ne souhaitez pas créer une nouvelle matrice de l'autre type, accédez aux éléments à l'aide de la fonction appropriée (dans l'exemple cv::Mat::at<unsigned char>) et convertissez le résultat en float.

Il existe également une différence entre le nombre de composants et un cv::Mat de CV_8UC3 le type est différent d'une image de CV_8UC1 type et ne devrait (généralement) pas être accessible par cv::Mat::at<unsigned char>, mais cv::Mat::at<cv::Vec3b>.

EDIT: En voyant la réponse de Martin, il se peut que vous soyez au courant de tout cela et ses explications correspondent davantage à ce que vous cherchiez.

64
Christian Rau