Comment consulter/modifier un élément de la matrice dans OpenCV? Pourquoi à() est templatized?
Dois-je savoir Mat
type d'élément pour utiliser at()
correctement? Par exemple, si j'ai
Mat rose = Mat(1,180, CV_64F, 0);
alors je peux appeler
rose.at<short>(i,j)++;
Si non, alors le modèle argument dois-je utiliser?
Pourquoi Mat::at
est templatized tout Mat
lui-même ne l'est pas?
Mise à JOUR
Cette question contenait un exemple de code avec une autre erreur, qui est maintenant ici: Comment remplir la Matrice de zéros dans OpenCV?
En gros, oui. Il est de votre responsabilité de connaître ou de découvrir avec
Vérifiez aussi ceci.
Ainsi, dans l'exemple ci-dessus, je sais que le type ou pourrait le découvrir. Quelle est la prochaine étape?
Vous la connaissez. CV_64f est pour "la Vision par Ordinateur _ 64 bits à virgule flottante de type". C'est le double précision en virgule flottante ou communément connu comme
Mat.type()
.Vérifiez aussi ceci.
Ainsi, dans l'exemple ci-dessus, je sais que le type ou pourrait le découvrir. Quelle est la prochaine étape?
CV_64F
est une valeur d'exécution, je ne peux pas l'utiliser dans at
paramètre du modèle.Vous la connaissez. CV_64f est pour "la Vision par Ordinateur _ 64 bits à virgule flottante de type". C'est le double précision en virgule flottante ou communément connu comme
double
. Vous pouvez en apprendre plus dans OpenCV documentation.Mat rose = Mat(1,180, CV_64F, 0);
et rose.at<double>(i,j)++;
OriginalL'auteur Suzan Cioc | 2013-06-11
Vous devez vous connecter pour publier un commentaire.
Comme bien d'ores et déjà souligné par William, vous devez fournir le bon type comme un argument de modèle pour
at
. Je crois quecv::Mat
lui-même n'est pas faite de modèle pour la simplification. Cependant, OpenCV équipage s'efforce de soutenir des fonctionnalités C++, y compris les modèles. L'interface est devenue légèrement hétérogène de cette façon.Vous ne pouvait pas déduire compilateur le type d'une variable de type à l'exécution, pour une raison évidente. Cependant, vous pouvez déduire au moment de la compilation, si votre variable de type est connu à ce point, à l'aide d'une classe de traits:
Dans ce cas, vous pouvez modifier la valeur de
type
et n'aurait pas besoin de changer les types manuellement pour tous lesat
ou d'autres appels de méthodes.double
ne fonctionne pas pour moi avecCV_64F
c'est ce que tous les propos. J'ai essayédouble
dès le début, parce que j'ai bien évidemment lire les docs surCV_64F
. Pls voir mes mises à jour.Le dernier argument pour
cv::Mat
constructeur dans votre cas est un pointeur à l'utilisateur les données allouées, pas la valeur par défaut de remplissage de l'image. Donc dans votre cas vous essayez d'accéder à la mémoire à zéro de l'adresse. Se débarrasser de lui, et vous êtes fine. Ou le remplacer parcv::Scalar(0)
.OriginalL'auteur Mikhail
Bien maintenant votre édité post diffère. Corrigé:
ou essayer différentes:
Vous devez utiliser le cv de structures comme des valeurs. Utilisation
cvScalar(0)
à la place.Je sais que j'ai corrigé votre erreur, mais je suis d'accord pour donner des crédits à la grande extrait de Mikhaïl proposé. Néanmoins, la vignette de votre question est mal, basé sur votre exemple de code.
Je peux enlever le code de l'échantillon car elle contient des erreurs. Oui, vous avez fixé, mais sans aucune explication. Aussi, vous ne produisaient pas d'explication quand il n'y avait pas d'échantillon. Donc vous méritez simplement plus, alors que @Mikhail a donné une réponse complète à la question d'origine.
:))))))))))))))
OriginalL'auteur William
La
Mat
classe n'est pas une classe de modèle, ce qui permet de changer son "type" au moment de l'exécution. Changer le type est utile par exemple lorsque la lecture à partir d'un fichier. N'étant pas un modèle pratique, lors de l'utilisation d'unMat
en tant que paramètre de la fonction, puisque la fonction n'est pas nécessaire d'être un modèle de fonction.Cependant, pour accéder à des éléments uniques (avec les pointeurs, au ou les itérateurs) vous avez besoin du type de données. Je suppose que c'est fait pour des raisons de performances. Cela va à l'encontre de l'exécution type de système et le rend plus difficile à écrire du code générique, lorsque vous ne connaissez pas le type au moment de la compilation. Néanmoins, vous pouvez le faire avec une solution de contournement.
La méthode la plus simple est tout simplement d'utiliser un if-else-cascade:
Mais vous pouvez imaginer que cela devient lourd, si vous écrivez pour tous les types et les canaux. Vous devez limiter le nombre de canaux de toute façon, car il n'y a aucune limite à l'utilisation d'OpenCV. Nous choisissons 4 ci-après.
J'ai écrit un helper modèle metaprogram en-tête, qui fait le travail. Vous pouvez fournir un foncteur avec basé sur un modèle
operator()
. Appelez ensuite le modèle metaprogram, qui va appeler le foncteur avec un temps de compilation type. Voir cet exemple pour un foncteur qui imprime le premier pixel et retourne si elle n'est pas nulle:Note, le type de retour de la
operator()
peut être arbitraire, mais ne peut pas dépendre du type d'imagecv_type
malheureusement. C'est parce qu'il est également utilisé comme type de retour de la fonction qui détient le si-sinon cascade (larun
fonction, voir ci-dessous).Voici le code appelant, qui peut vérifier pour "tous" les canaux (1 à 4) et les types ou pour un ensemble spécifié:
Le dernier appel va lever une exception, si
t
n'est pasCV_8UC1
ouCV_8UC3
. Si vous êtes souvent en utilisant la même restriction, vous pouvez abréger, avec l'aide de déclaration (voir au bas de l'en-tête de fichier ci-dessous).Donc, c'est un outil facile à utiliser la solution qui vous permet d'utiliser un temps de compilation valeur "fabriqué" à partir d'un moment de l'exécution de la valeur. Mais rappelez-vous, dans le fond d'un si-sinon-cascade est en train de faire toutes les vérifications (dans l'ordre dans lequel les canaux et les types ont été spécifiée). Cela implique que pour chaque combinaison de canal et le type est vérifié un béton foncteur classe est générée. S'il est grand, ce qui pourrait être mauvais. Il ne doit inclure le type charge des parties. Il pourrait également être une usine foncteur qui instancie basé sur un modèle de classe avec un non-modèle de base avec des fonctions virtuelles pour réduire la taille du code.
Il suit le fichier d'en-tête, qui contient le
CvTypeTraits
classe et le modèle metaprogram fonctions. En bas, vous pouvez voir que leCallFunctor
type est vraiment juste une abréviation pour une "restriction" de types et de canaux. Vous pouvez également déclarer quelque chose comme ça avec d'autres restrictions.OriginalL'auteur John