Hadoop对图像处理还是一个新兴的研究方向,我们可以从下图看出hadoop处理图像的流程: 图二 hadoop处理图像流程 1:图像文件的MapReduce数据流MapReduce的工作过程分为两个阶段:Map阶段和Reduce阶段。如图三所示: 用户程序直接把需要处理的图片文件对应路径告诉MapReduce框架,作为MapReduce程序的输入。ImageInputFormat对输入进行划分,ImageRecordReader对输入,进行记录读取,取得key值为ImageSplit对象的路径,value值为ImageWritable。MapReduce框架把读取的<key,value>对传递给map程序进行执行,map程序对图片进行相关操作后,利用reduce程序将处理后的图像分片进行整合,得到处理后的整个图像文件。Reduce程序将构建的对象传递给ImageOutputFormat进行输出。
2:自定义数据类型:ImageWritable类Hadoop通过Writable对消息进行序列化。Writable接口定义了输入输入流的基本方法,MapReduce程序用他来序列化键 /值对。实验实现了自定义的ImageWritable对图像文件进行编码。 Writable接口定义了两个方法:一个用于将其状态写入二进制格式的DataOutput流,另一个用于从二进制格式的DataInput流读取其状态。ImageWritable重写了这两个方法,分别写入和读出图片的相关数据:图片的高度和宽度,源图像的y轴高度,图像的路径和图像的像素信息。 (1) 输入格式:ImageInputFormat.ImageInputFormat继承了FileInputFormat类。FileInputFormat是所有使用文件作为数据源的InputFormat实现的基类。ImageInputFormat负责产生输入分片并将它们分割成记录。指定ImageRecordReader将输入分割成记录,用户可以定义记录的大小,他小于或等于分片ImageSplit。键是Text类型,存储该子图片在文件系统的路径。值是一个记录,它是ImageWritable类型。 (2) 记录阅读器:ImageRecordReader。Map任务使用ImageRecordReader来读取记录并且生成键/值对<Text,ImageWritable>,然后传递给mao函数。ImageRecordReader重写了RecordReader定语的所以函数。其基本构造。ImageRecordReader的nextKeyValue()方法是得到下一个键/值对,键位当前的处理的键,值通过计算得到的下一个记录要处理的图像的分片。用户可以自定义ImageWriatble的大小,ImageRecordReader的getConfig()方法用来接受用户传递的数据。Getconfig()函数主要接收3个参数:ImageWritable的大小,需要利用的相邻像素点的便边界个数和当前处理的图像是否为彩色图像。 图三MapReduce 数据流
Hadoop编码实现图像的分割Hadoop运行中FileInputFormat都是默认一行读取的,所以必须重载文件输入流,本文中派生出JPEGFileInputFormat,JPEGFileOutputFormat文件流。 图像分割的核心代码Mapper实现
- public static class MyMapper extends Mapper<ImageHeader, FloatImage,Text, IntWritable>
- {
- private Path path;
- private FileSystem fileSystem;
- private Configuration conf;
- private float red;
- private float greed;
- private float blue;
- private int width;
- private int high;
- private final static IntWritable one=new IntWritable(1);
- private Text word=new Text();
- public void setup(Context jc) throws IOException
- {
- conf = jc.getConfiguration();
- fileSystem = FileSystem.get(conf);
- path = new Path( conf.get("im2gray.outdir"));
- fileSystem.mkdirs(path);
- }
- public void map(ImageHeader key, FloatImage value, Context context) throws IOException, InterruptedException{
- if (value != null) {
- //FloatImage gray = value.convert(FloatImage.RGB2GRAY);
- width=value.getWidth();
- high =value.getHeight();
- for(int i=0;i<width;++i)
- for(int j=0;j<high;++j)
- {
- red=value.getPixel(i,j,0);
- context.write(new Text("R "+(int)(red*255+0.5)),one);
- greed=value.getPixel(i,j,1);
- context.write(new Text("G "+(int)(red*255+0.5)),one);
- blue=value.getPixel(i,j,2);
- context.write(new Text("B "+(int)(red*255+0.5)),one);
- }
- }
- else
- context.write(new Text(""), new IntWritable(0));
- }
- }
复制代码
Reduce实现 - public void reduce(Text key, Iterable<IntWritable> values, Context context)
- throws IOException, InterruptedException
- {
-
- int sum=0;
- for (IntWritable val : values)
- {
- sum+=val.get();
- }
- result.set(sum);
- context.write(key,result);
-
- }
- }
复制代码
总的来说,本文在hadoop分布式环境中是对一个JPG进行分割读取,并统计RGB值,对统计后的结果绘制直方图。
更多内容 |