c语言-RAW格式图片原始数据中值滤波

吐槽:

先贴一个可以在线看RAW格式图片的网站:Photopea | Online Photo Editor

什么迅捷转换器,ADCsee(好像叫这玩意),各种在线转的网站都不好使,目前我发现的就这个在线网站的和PS可以打开RAW图片

RAW图片可真是让人烦啊,搜了很多资料都是在介绍RAW是什么,原理是什么。没有找到其他教程说如何处理RAW原始数据。

正文:

出于工作需要,要将RAW格式的图片直接进行滤波,然后再转为BMP。直接滤波然后转BMP和先转BMP再滤波,肯定是不同的。不过从16位的RAW到8位的BMP肯定会丢失细节。

要操作原始图片数据就要知道RAW图片的存储格式,由哪几部分构成,很可惜,这部分相关资料也没找到。有推荐的可以告诉我,先十分感谢~

只找到了读取RAW图片的字节流文章,也够用了。

需要处理的lena.raw图片的字节流读取:
我拿到的图是纯数据字节流,即全部都是数据,不像BMP有头信息,位图信息之类的,它全是数据
width = 160 (pixel)
height = 120 (pixel)
且是16bit的小端模式存储,图片的大小为160*120*2=38400字节

raw常用的数据格式:RAW8,RAW10,RAW12,什么意思呢?用几位来表示一个像素,RAW8就是用8位表示一个像素,RAW10是用10位表示一个像素,10需要两个字节,多出的6位没用,补0,RAW12也一样

关于下图的数据,会发现是使用的RAW12,因为只使用到了12位,其余4位是0,如下图是截取到的一些数据(PS:不要用notepad打开,notepad查看16进制一般都是有问题的)

---------使用fread读取,截取前一部分数据
一次读取一个字节
22  B  CC  9  3E  A  B0  A  B0  A  3E  A  3E  A  B0  A  3E  A  5A  9  3E  A  B0  A  CC  9  22  B  22

一次读取两个字节
B22 9CC  A3E  AB0  AB0  A3E  A3E  AB0  A3E  95A  A3E  AB0  9CC  B22  B22  C06  A3E  B94  A3E  AB0  95A

可以发现,读取两个字节时,自动将数据的大小端调整了,如22 B--->B22,那我就不用转大小端了

直接贴代码,代码有注释

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define	height  120
#define	width	160

typedef unsigned short BYTE;//要读两个字节所以使用unsigned short

int main()
{
	FILE *fp = NULL,*fp2 = NULL;
	FILE *fpw;
	
	BYTE B[height*width];
	BYTE *ptr;
	
	int i,j,m,,x,y;

	int flag,temp;

	unsigned short pixel[9]={0};
	//打开图片
	if((fp = fopen( "lena.raw", "rb" )) == NULL)
	{
	    printf("can not open the raw image \n" );
	    return 0;
	}
	else
    {
        printf("read OK\n");
    } 
	
	// 分配内存并将图像读到一维数组中    
	ptr = (BYTE*)malloc( width * height * sizeof(BYTE) );
	for( i = 0; i < height*width; i++ )
	{
		
		fread( ptr, 2, 1, fp );
		B[i]= *ptr;	
		//printf("B[%d] = %X\n",i,B[i]);
		ptr++;
	
	}
	fclose(fp);


// 这里可以对一维数组中的图像数据进行处理
for(j=1;j<height-1;j++)
{
	for(i=1;i<width-1;i++)
	{
		//将3×3滑动窗口中的所有像素值放入pixel[m]
		m=0;
		for(y=j-1;y<=j+1;y++)
		{
			for(x=i-1;x<=i+1;x++)
			{
				pixel[m]=B[y*width+x];
				m=m+1;
			}
		}
		
		//让一维数组pixel[9]进行降序排列
		do 
		{
			flag=0;//循环结束的标志
			for(m=0;m<9;m++)
			{
				if(pixel[m]<pixel[m+1])
				{
					temp = pixel[m];
					pixel[m] = pixel[m+1];
					pixel[m+1] = temp;
					flag=1;
				}//if
			}//for
		} while (flag==1);
		B[width*j+i]=pixel[4];
	}
}


// 将处理后的图像数据输出至done.raw
if( ( fpw = fopen( "done.raw", "wb" ) ) == NULL )
{
    printf("can not create the done.raw \n");
    return 0;
}

for( i = 0; i < height*width; i++ )
{
    
		fwrite( &B[i], 2 , 1, fpw );
		//printf("B[%d] = %X\n",i,B[i]);
}

fclose(fpw);//释放指针
return 0;
}



以下就是我要处理的图,滤波后基本看不出效果,因为正常RAW格式的图大小都在几十兆,这个是领导给我的,纯数据的图,38k左右,滤波算法跟另一篇文章C语言-BMP滤波是一毛一样的,想看其他图片滤波效果的可以去看看

 别看就这一丢丢内容,对于刚工作的我来说,搞了一个星期呢!

如有出错误欢迎指正!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴能为您解答问题!关于用C语言实现一维数据滤波,可以参考以下代码实现: ```c #include <stdio.h> // 滤波 int median_filter(unsigned char *input, unsigned char *output, int length, int window_size) { int half = window_size / 2; // 滑动窗口大小的一半 unsigned char temp[window_size]; // 临时保存数据的数组 int i, j, k, top; // i: 表示窗口窗口左边界,j: 表示窗口右边界,k: 表示数据的下标,top: 为计数器 // 开始滤波,从第一个数据开始到倒数第二个数据 for (i = 0, j = window_size - 1, k = half; j < length; i++, j++, k++) { // 将数据移入临时数组,进行排序 for (top = 0; top < window_size; top++) { temp[top] = input[top + i]; } // 冒泡排序 for (top = 0; top < window_size - 1; top++) { for (int m = top + 1; m < window_size; m++) { if (temp[top] > temp[m]) { unsigned char t = temp[top]; temp[top] = temp[m]; temp[m] = t; } } } // 找到间数 output[k] = temp[half]; } return k - half; // 返回滤波数据的长度 } int main() { unsigned char input[] = { 10, 30, 20, 40, 50, 10, 30, 20, 50, 20 }; unsigned char output[10]; int length = sizeof(input) / sizeof(unsigned char); int window_size = 3; int result_length = median_filter(input, output, length, window_size); printf("Input: "); for (int i = 0; i < length; i++) { printf("%d ", input[i]); } printf("\nOutput: "); for (int i = 0; i < result_length; i++) { printf("%d ", output[i]); } return 0; } ``` 代码实现了一个简单的滤波算法,输入为一个一维数据(数组),输出为滤波后的数据。该算法采用滑动窗口的方式对数据进行处理,经过排序后找到每个窗口的位数作为该窗口的输出。输入的数据和输出的数据都是 `unsigned char` 类型的数组, `length` 表示输入数据的长度, `window_size` 表示滑动窗口的大小。调用方式为 `median_filter(input, output, length, window_size)`,返回为输出数据的长度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值