如何在MATLAB中读取RAW图像?

3

我想在MATLAB中打开和读取一个.raw图像。 我的文件可以从这里下载。 我尝试了以下三个代码片段,但都没有给出预期结果。

代码片段 #1

    row=576;  col=768;
    fin=fopen('m-001-1.raw','r');
    I=fread(fin,row*col,'uint8=>uint8'); 
    Z=reshape(I,row,col);
    Z=Z';
    k=imshow(Z);

它展示了这张图片:

first

代码片段 #2

    f=fopen('m-001-1.raw');
    a=fread(f);
    input_img = reshape(a,768, 576, 3);
    input_img = imrotate(input_img, -90);
    imwrite(input_img, 'm-001-1.jpg'); 

这将以.jpg格式保存一张空白图片。

代码片段 #3

    id = fopen('m-001-1.raw', 'r');
    x = fread(id, [576,768], 'short');

当我使用imshow(x)时,显示的是这张图片:third。如何正确地读取这张图片?
2个回答

6

你的行/列大小反了。由于MATLAB数组是按列主要存储的,而栅格图像通常是按行主要存储的,因此你需要将图像读取为[col row]矩阵,然后转置它。

row=576;  col=768;
fin=fopen('m-001-1.raw','r');
I=fread(fin, [col row],'uint8=>uint8'); 
Z=I';
k=imshow(Z)

图像复制是由于你每行短了768-576=192个像素,所以每行都逐渐偏移这么多。在4行之后,您已经弥补了差距(4*192 = 768),因此您有4个图像的复制品。

嗯,我应该看到那个的。Peter发现得好。 - rayryeng
谢谢,你是对的,但是数据库中的图像是彩色图像,当我运行这段代码时,它显示给我一张灰色的图像。 - Simin Soleymanpour
这是因为上面的代码只读取了第一个通道。我很快会写一个可以读取全部三个通道的答案。 - rayryeng
@SiminSoleymanpour - 你需要更多帮助吗?考虑接受我们的答案之一。 - rayryeng
谢谢Peter的帮助。"Stackoverflow"非常好。我感谢你们在这个网站上的工作。我向认识的每个人介绍了它。 - Simin Soleymanpour

4

Peter的代码(顺便感谢!)假设您的图像是灰度的。对于彩色图像,您需要将所有字节读入单个1D数组,因为我们无法使用fread将数据读入为3D矩阵(至少不是我所知道的...)。然后,我们将其重新整形为3D矩阵。在我们重塑矩阵之后,请注意这是转置结果。因此,我们将不得不分别转置每个通道,或者聪明地组合flipdimimrotate来为我们执行3D转置。我会将图像旋转90度顺时针,但这会使图像在列上镜面反射。然后我使用flipdim,第二个参数为2,因为我想在列上镜像反射以获取原始图像。

因此,您实际上需要执行以下操作:

row=576;  col=768;
fin=fopen('m-001-1.raw','r');
I=fread(fin, col*row*3,'uint8=>uint8'); %// Read in as a single byte stream
I = reshape(I, [col row 3]); %// Reshape so that it's a 3D matrix - Note that this is column major
Ifinal = flipdim(imrotate(I, -90),2); % // The clever transpose
imshow(Ifinal);
fclose(fin); %// Close the file

我得到的是这张图片:

在此输入图片描述


或者,你当然可以使用Peter的代码,但你需要使用它来逐个颜色平面重建图像。换句话说,你可以这样做:
row=576;  col=768;
fin=fopen('m-001-1.raw','r');
I1=fread(fin, [col row],'uint8=>uint8'); %// Red channel
I2=fread(fin, [col row],'uint8=>uint8'); %// Green channel
I3=fread(fin, [col row],'uint8=>uint8'); %// Blue channel
I1 = I1.'; I2 = I2.'; I3 = I3.'; %// Transpose each channel separately
Ifinal = cat(3, I1, I2, I3); %// Create 3D matrix
imshow(Ifinal);
fclose(fin);

您将获得与上述图片完全相同的图像。

2
谢谢你的帮助,这已经是你第二次帮助我了。 - Simin Soleymanpour
@rayryeng:这很有道理。我猜一个hack的方法是先用size(imread(img))?另外,我认为permute(img, [2,1,3])也可以用于转置。或者如果需要镜像,可以使用flip(permute(img, [2,1,3,]), 2) - marcman
@marcman 我正在修改我的帖子以这种方式进行转置...这是一篇旧帖子。谢谢。 - rayryeng
@marcman 是的...那将是一个不错的“hack”,但这假设您已经在内存中加载了其中一张图片。这是情况吗?我假设您事先什么都不知道。 - rayryeng
@rayryeng:不一定。因为您还在原始文件上执行标准的imread调用,所以肯定会增加一些开销。但我想这应该能完成工作。我的理解是,imread('image.raw')上的尺寸将与正确的尺寸匹配(来源:此帖子)。 - marcman
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接