ti-enxame.com

Quais são as diferenças entre CV_8U e CV_32F e com o que devo me preocupar ao converter entre elas?

Eu tenho algum código que está funcionando e suspeito que seja porque estou operando nos tipos de dados incorretos ou fazendo uma conversão ruim entre eles.

Ele está misturando cv::Mat objetos dos tipos CV_8U (que é criado ao ler um jpg como escala de cinza com cv::imread), CV_32F e CV_32S.

Quais são as diferenças entre esses tipos de dados e do que preciso ter certeza ao converter entre eles?

47
mic

CV_8U não possui 8 bits/pixel - isto é, um pixel pode ter valores de 0 a 255, este é o intervalo normal para a maioria dos formatos de imagem e vídeo.

CV_32F é flutuante - o pixel pode ter qualquer valor entre 0-1,0, isso é útil para alguns conjuntos de cálculos de dados - mas deve ser convertido em 8 bits para salvar ou exibir multiplicando cada pixel por 255.

CV_32S é um valor inteiro assinado de 32 bits para cada pixel - novamente útil para você fazer cálculos inteiros nos pixels, mas novamente precisa ser convertido em 8 bits para salvar ou exibir. Isso é mais complicado, pois você precisa decidir como converter um intervalo muito maior de valores possíveis (+/- 2 bilhões!) Em 0-255

86
Martin Beckett

Basicamente, eles apenas descrevem quais são os componentes individuais:

  • _CV_8U_: número inteiro não assinado de 1 byte (_unsigned char_).

  • _CV_32S_: número inteiro assinado de 4 bytes (int).

  • _CV_32F_: ponto flutuante de 4 bytes (float).

O que você sempre deve ter em mente é que não pode simplesmente convertê-los de um para o outro (ou provavelmente não fará o que você deseja), especialmente entre tipos de tamanhos diferentes.

Portanto, sempre use funções de conversão reais para converter entre elas, como _cv::convert_ ou _cv::Mat::convertTo_. Não tente acessar os elementos de, por exemplo, a _cv::Mat_ do tipo _CV_8U_ usando por ex. _cv::Mat::at<float>_ ou _cv::Mat_<float>_.

Ou se você deseja converter elementos individuais e não deseja criar uma nova matriz do outro tipo, acesse os elementos usando a função apropriada (no exemplo _cv::Mat::at<unsigned char>_) e converta o resultado em float.

Da mesma forma, também existe uma diferença entre o número de componentes e o tipo _cv::Mat_ de _CV_8UC3_ é diferente de uma imagem do tipo _CV_8UC1_ e (geralmente) não deve ser acessado por _cv::Mat::at<unsigned char>_, mas por _cv::Mat::at<cv::Vec3b>_.

EDIT: Vendo a resposta de Martin, pode ser que você esteja ciente disso tudo e as explicações dele sejam mais o que você estava procurando.

64
Christian Rau