我正在编写一段代码,在其中我读取、成像和处理它并得到一个Mat of double/float
。我正在将其保存到一个文件中,稍后,我正在从该文件中读取它。
1Kx1K 图像所需的空间为 8MB,当我使用 float 时,它为 4MB。所以我想使用float
.
这是我的代码和输出:
Mat data = readFloatFile("file_location");
cout << data.at<float>(0,0) << " " << data.at<double>(0,0);
当我在DEBUG mode
中运行此代码时,浮点数的打印输出-0
,双精度给出异常,即assertion failed
。但是当我使用RELEASE mode
浮点数的打印输出是 -0
和 0.832 的双精度,这是真正的值。
我的问题是为什么我在使用data.at<float>(0,0)
时无法获得输出,为什么当我使用data.at<double>(0,0) in RELEASE mode
时我没有得到异常,应该是这种情况?
编辑:这是我编写和读取的代码
void writeNoiseFloat(string imageName,string fingerprintname) throw(){
Mat noise = getNoise(imageName);
FILE* fp = fopen(fingerprintname.c_str(),"wb");
if (!fp){
cout << "not found ";
perror("fopen");
}
float *buffer = new float[noise.cols];
for(int i=0;i<noise.rows;++i){
for(int j=0;j<noise.cols;++j)
buffer[j]=noise.at<float>(i,j);
fwrite(buffer,sizeof(float),noise.cols,fp);
}
fclose(fp);
free(buffer);
}
void readNoiseFloat(string fpath,Mat& data){
clock_t start = clock();
cout << fpath << endl;
FILE* fp = fopen(fpath.c_str(),"rb");
if (!fp)perror("fopen");
int size = 1024;
data.create(size,size,CV_32F);
float* buffer= new float[size];
for(int i=0;i<size;++i) {
fread(buffer,sizeof(float),size,fp);
for(int j=0;j<size;++j){
data.at<float>(i,j)=buffer[j];
cout << data.at<float>(i,j) << " " ;
cout << data.at<double>(i,j);
}
}
fclose(fp);
}
提前感谢,
首先,您不能在一个cv::Mat
中使用float
和double
,因为存储本身只是字节数组。对于float
矩阵和double
矩阵,此数组的大小将不同。
因此,您必须决定使用什么。
从本质上讲,data.at<type>(x,y)
等同于(type*)data_ptr[x][y]
(请注意,这不是确切的代码,其目的是显示正在发生的事情)
编辑:根据您添加的代码,您正在创建CV_32F
矩阵,这意味着您必须使用 float
来编写、读取和元素。使用双重会导致价值的重新解释,并且肯定会给您一个不正确的结果。
关于断言,我确信在cv::MAT::at<class T>
内部有以下代码:
assert(sizeof<T>==this.getDepth());
通常断言仅在DEBUG
模式下编译,因此这就是为什么您不会在RELEASE
中给出此错误的原因。
编辑2:不考虑问题,但切勿将free()
与new
一起使用,也不要将delete
与malloc()
一起使用。结果可能是一个几乎无法调试的问题。
因此,请使用delete[]
作为缓冲区。
调试和发布之间的区别:
您的代码中存在错误。它只是不显示在发布模式下。这就是调试器的用途。调试器会告诉您代码是否存在任何错误/问题,发布只是通过它运行......此外,编译器优化您的代码以运行得更快,因此更小,调试器在您的 HD 上使用更大的大小,因为您实际上可以调试它。
发布将未初始化的变量初始化为 0。这可能因不同的编译器而异。