轉載請標明處:
作者:微微蘇荷
近日,用QT和mxnet結合做一個圖像識別的demo。遇到需要把圖片從QImage轉為vector單色分離的格式的要求,用來識別時輸入。
經實踐,找到3種方法,分享給大家:
需要注意的是,QImage的存儲順序是 BGRA(opencv也是這樣反着的),不是正常口述RGBA.
另:mx_float == float
一.
int image_size = width * height * channels; //圖像的寬/高/通道數(除去了A通道)
std::vector<mx_float> image_data = std::vector<mx_float>(image_size);
mx_float* ptr_image_r = image_data.data();
const uchar* pData= image.constBits(); // 獲取圖像原始數據
mx_float* ptr_image_g = image_data.data() + image_size / 3;
mx_float* ptr_image_b = image_data.data() + image_size / 3 * 2;
for (int i = 0; i < height; i++){
int lineNum_32 = i * width * 4;
for (int k = 0; k < width; k++){
if(1 < IMAGE_CHANNELS){
// 乘以4的原因是QImage是四個通道存儲的,BGRA,所以每個像素都占有4個字節。
*ptr_image_r++ = static_cast<mx_float> (pData[lineNum_32 + k * 4 + 2]) ;
*ptr_image_g++ = static_cast<mx_float> (pData[lineNum_32 + k * 4 + 1]);
}
*ptr_image_b++ = static_cast<mx_float> (pData[lineNum_32 + k * 4 ]) ;
}
}
二.利用image.scanLine(),獲取每行掃描線的首地址
int image_size = width * height * channels; //圖像的寬/高/通道數(除去了A通道)
std::vector<mx_float> image_data = std::vector<mx_float>(image_size);
mx_float* ptr_image_r = image_data.data();
const uchar* pData= image.constBits(); // 獲取圖像原始數據
mx_float* ptr_image_g = image_data.data() + image_size / 3;
mx_float* ptr_image_b = image_data.data() + image_size / 3 * 2;
for (int i = 0; i < height; i++){
uchar *imageScanLine = image.scanLine(i);
for (int k = 0; k < width; k++){
if(1 < IMAGE_CHANNELS){
// 乘以4的原因是QImage是四個通道存儲的,BGRA,所以每個像素都占有4個字節。
*ptr_image_r++ = static_cast<mx_float>(\
imageScanLine[k * 4 + 2]) ;
*ptr_image_g++ = static_cast<mx_float>(\
imageScanLine[k * 4 + 1]) ;
}
*ptr_image_b++ = static_cast<mx_float>(\
imageScanLine[k * 4]) ;
}
}
三.最可靠最簡潔的方法.但是可能性能比上兩個稍微差些(沒有評估),因為他每個像素都要從QImage獲取一次,不確定會不會比一次獲取完和一次獲取一行有性能之差,但個人感覺不會,因為QImage也是在內存中,不存在文件IO。但是他很簡單,不需要考慮圖片的位深和存儲順序/大端小端等問題。
int image_size = width * height * channels; //圖像的寬/高/通道數(除去了A通道)
std::vector<mx_float> image_data = std::vector<mx_float>(image_size);
mx_float* ptr_image_r = image_data.data();
const uchar* pData= image.constBits(); // 獲取圖像原始數據
mx_float* ptr_image_g = image_data.data() + image_size / 3;
mx_float* ptr_image_b = image_data.data() + image_size / 3 * 2;
for (int i = 0; i < height; i++){
uchar *imageScanLine = image.scanLine(i);
for (int k = 0; k < width; k++){
// 沒有做兼容單通道
QRgb bits = image.pixel(i, k);
*ptr_image_r++ = static_cast<mx_float>(qRed(bits)) ;
*ptr_image_g++ = static_cast<mx_float>(qGreen(bits));
*ptr_image_b++ = static_cast<mx_float>(qBlue(bits)) ;
}
}
