web-dev-qa-db-fra.com

Changer le type d'objet Mat de CV_32F à CV_8U

J'ai essayé d'afficher une image de type CV_32F en utilisant la fonction imshow mais elle a montré une image BLANCHE . Dans le Documentation son étant donné que les images en virgule flottante seront mappées à 0-255 et affichées, mais cela montrait juste une image blanche. J'ai essayé de la convertir en CV_8U en utilisant

Mat A = Mat :: ones (300,300, CV_32FC1) * 1000;

faire un peu de traitement - attribuer des valeurs flottantes aux pixels dans A

......

Mat B;

A.convertTo (B, CV_8U)

Lorsque je montre "B", j'obtiens une image en noir et blanc, il n'y a aucune nuance de gris . Les pixels flottants de A sont-ils correctement mappés sur 0-255? Suis-je en train de faire quelque chose de mal?

Peu de valeurs dans A sont 1000 comme initialisées et reste sont des nombres à virgule flottante qui sont attribués pendant le traitement.

31
Karthik Murugan

Dans OpenCV, si l'image est de type virgule flottante, seuls ces pixels peuvent être visualisés à l'aide de imshow, qui ont une valeur de 0,0 à 1,0, si la valeur est supérieure à 1,0, elle sera affichée en blanc pixel et si moins de 0,0, il sera affiché comme pixel noir. Pour visualiser une image à virgule flottante, mettez ses valeurs à l'échelle dans la plage 0.0 - 1.0.

Quant à la partie de conversion .... Lorsqu'elle est utilisée avec des arguments par défaut, la fonction cv::Mat::convertTo Crée simplement une matrice du type spécifié, puis copie les valeurs de la matrice source et les arrondit à la valeur la plus proche possible du type de données de destination. Si la valeur est hors plage, elle est fixée aux valeurs minimale ou maximale.

Dans la documentation de imshow, il est écrit que:

Si l'image est en virgule flottante 32 bits, les valeurs des pixels sont multipliées par 255. En d'autres termes, la plage de valeurs [0,1] est mappée sur [0,255].

Cela signifie que seules les valeurs comprises entre 0,0 et 1,0 seront mappées entre 0 et 255. Si une valeur est supérieure à 1,0 et multipliée par 255, elle deviendra supérieure à 255. Elle sera ensuite limitée à la plage de CV_8U Et finalement il deviendra également 255.

Dans votre exemple, toutes les valeurs qui sont 1000 deviendront 255 dans la matrice de destination car le type de destination est CV_8U Et la valeur maximale possible est 255. Toutes les valeurs à virgule flottante seront floored . Aucun mappage automatique n'est effectué.

Pour mapper correctement les valeurs à la plage de CV_8U, Utilisez les 3e et 4e paramètres de la fonction cv::Mat::convertTo, De sorte que les valeurs soient mises à l'échelle avant la conversion.

Supposons que la matrice A ait des valeurs minimale et maximale Min et Max, où Min!=Max.

Pour mettre à l'échelle correctement les valeurs de 0 à 255, vous pouvez procéder comme suit:

if (Min!=Max){ 
    A -= Min;
    A.convertTo(B,CV_8U,255.0/(Max-Min));
}

Vous pouvez également le faire directement comme ceci:

if (Min!=Max)
    A.convertTo(B,CV_8U,255.0/(Max-Min),-255.0*Min/(Max-Min));

(édité en tenant compte du commentaire de zhangxaochen)

56
sgarizvi