1.概述

  最近在和人交流时谈到数据相似度和数据共性问题,而刚好在业务层面有类似的需求,今天和大家分享这类问题的解决思路,分享目录如下所示:

  • 业务背景
  • 编码实践
  • 预览截图

  下面开始今天的内容分享。

2.业务背景

  目前有这样一个背景,在一大堆数据中,里面存放着图片的相关信息,如下图所示:

  上图只是给大家列举的一个示例数据格式,第一列表示自身图片,第二、第三......等列表示与第一列相关联的图片信息。那么我们从这堆数据中如何找出他们拥有相同图片信息的图片。

2.1 实现思路

  那么,我们在明确了上述需求后,下面我们来分析它的实现思路。首先,我们通过上图所要实现的目标结果,其最终计算结果如下所示:

pic_001pic_002 pic_003,pic_004,pic_005
pic_001pic_003 pic_002,pic_005
pic_001pic_004 pic_002,pic_005
pic_001pic_005 pic_002,pic_003,pic_004
......

  结果如上所示,找出两两图片之间的共性图片,结果未列完整,只是列举了部分,具体结果大家可以参考截图预览的相关信息。

  下面给大家介绍解决思路,通过观察数据,我们可以发现在上述数据当中,我们要计算图片两两的共性图片,可以从关联图片入手,在关联图片中我们可以找到共性图片的关联信息,比如:我们要计算pic001pic002图片的共性图片,我们可以在关联图片中找到两者(pic001pic002组合)后对应的自身图片(key),最后在将所有的key求并集即为两者的共性图片信息,具体信息如下图所示:

  通过上图,我们可以知道具体的实现思路,步骤如下所示:

  • 第一步:拆分数据,关联数据两两组合作为Key输出。
  • 第二步:将相同Key分组,然后求并集得到计算结果。

  这里使用一个MR来完成此项工作,在明白了实现思路后,我们接下来去实现对应的编码。

3.编码实践

  • 拆分数据,两两组合。
public static class PictureMap extends Mapper<LongWritable, Text, Text, Text> {

        @Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Text>.Context context)
throws IOException, InterruptedException {
StringTokenizer strToken = new StringTokenizer(value.toString());
Text owner = new Text(); Set<String> set = new TreeSet<String>(); owner.set(strToken.nextToken());
while (strToken.hasMoreTokens()) {
set.add(strToken.nextToken());
} String[] relations = new String[set.size()];
relations = set.toArray(relations); for (int i = 0; i < relations.length; i++) {
for (int j = i + 1; j < relations.length; j++) {
String outPutKey = relations[i] + relations[j];
context.write(new Text(outPutKey), owner);
} }
}
}
  • 按Key分组,求并集
public static class PictureReduce extends Reducer<Text, Text, Text, Text> {

        @Override
protected void reduce(Text key, Iterable<Text> values, Reducer<Text, Text, Text, Text>.Context context)
throws IOException, InterruptedException {
String common = "";
for (Text val : values) {
if (common == "") {
common = val.toString();
} else {
common = common + "," + val.toString();
}
}
context.write(key, new Text(common));
}
}
  • 完整示例
package cn.hadoop.hdfs.example;

import java.io.IOException;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import cn.hadoop.hdfs.util.HDFSUtils;
import cn.hadoop.hdfs.util.SystemConfig; /**
* @Date Aug 31, 2015
*
* @Author dengjie
*
* @Note Find picture relations
*/
public class PictureRelations extends Configured implements Tool { private static Logger log = LoggerFactory.getLogger(PictureRelations.class);
private static Configuration conf; static {
String tag = SystemConfig.getProperty("dev.tag");
String[] hosts = SystemConfig.getPropertyArray(tag + ".hdfs.host", ",");
conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://cluster1");
conf.set("dfs.nameservices", "cluster1");
conf.set("dfs.ha.namenodes.cluster1", "nna,nns");
conf.set("dfs.namenode.rpc-address.cluster1.nna", hosts[0]);
conf.set("dfs.namenode.rpc-address.cluster1.nns", hosts[1]);
conf.set("dfs.client.failover.proxy.provider.cluster1",
"org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
conf.set("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName());
conf.set("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName());
} public static class PictureMap extends Mapper<LongWritable, Text, Text, Text> { @Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Text>.Context context)
throws IOException, InterruptedException {
StringTokenizer strToken = new StringTokenizer(value.toString());
Text owner = new Text(); Set<String> set = new TreeSet<String>(); owner.set(strToken.nextToken());
while (strToken.hasMoreTokens()) {
set.add(strToken.nextToken());
} String[] relations = new String[set.size()];
relations = set.toArray(relations); for (int i = 0; i < relations.length; i++) {
for (int j = i + 1; j < relations.length; j++) {
String outPutKey = relations[i] + relations[j];
context.write(new Text(outPutKey), owner);
} }
}
} public static class PictureReduce extends Reducer<Text, Text, Text, Text> { @Override
protected void reduce(Text key, Iterable<Text> values, Reducer<Text, Text, Text, Text>.Context context)
throws IOException, InterruptedException {
String common = "";
for (Text val : values) {
if (common == "") {
common = val.toString();
} else {
common = common + "," + val.toString();
}
}
context.write(key, new Text(common));
}
} public int run(String[] args) throws Exception {
final Job job = Job.getInstance(conf);
job.setJarByClass(PictureMap.class);
job.setMapperClass(PictureMap.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
job.setReducerClass(PictureReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
FileInputFormat.setInputPaths(job, args[0]);
FileOutputFormat.setOutputPath(job, new Path(args[1]));
int status = job.waitForCompletion(true) ? 0 : 1;
return status;
} public static void main(String[] args) {
try {
if (args.length != 1) {
log.warn("args length must be 1 and as date param");
return;
}
String tmpIn = SystemConfig.getProperty("hdfs.input.path.v2");
String tmpOut = SystemConfig.getProperty("hdfs.output.path.v2");
String inPath = String.format(tmpIn, "t_pic_20150801.log");
String outPath = String.format(tmpOut, "meta/" + args[0]); // bak dfs file to old
HDFSUtils.bak(tmpOut, outPath, "meta/" + args[0] + "-old", conf); args = new String[] { inPath, outPath };
int res = ToolRunner.run(new Configuration(), new PictureRelations(), args);
System.exit(res);
} catch (Exception ex) {
ex.printStackTrace();
log.error("Picture relations task has error,msg is" + ex.getMessage());
} } }

4.截图预览

  关于计算结果,如下图所示:

5.总结

  本篇博客只是从思路上实现了图片关联计算,在数据量大的情况下,是有待优化的,这里就不多做赘述了,后续有时间在为大家分析其中的细节。

6.结束语

  这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!

MapReduce业务 - 图片关联计算的更多相关文章

  1. linq查询数值为null的问题以及数据表的关联计算问题

    说明:下面实例都是我进行项目开发时的真实部分代码,毫无保留 一.数据表的关联计算 //把当前年度的分差计算出来,建立两个关联的数据表 try { using(TransactionScope scop ...

  2. 【MapReduce】经常使用计算模型具体解释

    前一阵子參加炼数成金的MapReduce培训,培训中的作业样例比較有代表性,用于解释问题再好只是了. 有一本国外的有关MR的教材,比較有用.点此下载. 一.MapReduce应用场景 MR能解决什么问 ...

  3. ios 拉伸图片和计算文字的大小

    一.拉伸图片 /** * 传入图片的名称,返回一张可拉伸不变形的图片 * * @param imageName 图片名称 * * @return 可拉伸图片 */ + (UIImage *)resiz ...

  4. MapReduce单表关联学习~

    首先考虑表的自连接,其次是列的设置,最后是结果的整理. 文件内容: import org.apache.hadoop.conf.Configuration; import org.apache.had ...

  5. opencv 霍夫变换 实现图片旋转角度计算

    在OCR实际开发中,证件照采集角度有很大的偏差,需要将图片进行旋转校正, 效果图: 在应用中发现应该加入高斯模糊,可以极大减少误差线条. 知道线条后 通过求斜率 得旋转角度 .(x1-x2)/(y1- ...

  6. 使用mapreduce计算环比的实例

    最近做了一个小的mapreduce程序,主要目的是计算环比值最高的前5名,本来打算使用spark计算,可是本人目前spark还只是简单看了下,因此就先改用mapreduce计算了,今天和大家分享下这个 ...

  7. 大数据计算的基石——MapReduce

    MapReduce Google File System提供了大数据存储的方案,这也为后来HDFS提供了理论依据,但是在大数据存储之上的大数据计算则不得不提到MapReduce. 虽然现在通过框架的不 ...

  8. 【MySQL】pt-query-digest数据处理并关联业务

    参考:www.percona.com/doc/percona-toolkit/2.1/pt-query-digest.htm 通过pt-query-digest将慢日志导入数据库后在表global_q ...

  9. Caffe学习系列(15):计算图片数据的均值

    图片减去均值后,再进行训练和测试,会提高速度和精度.因此,一般在各种模型中都会有这个操作. 那么这个均值怎么来的呢,实际上就是计算所有训练样本的平均值,计算出来后,保存为一个均值文件,在以后的测试中, ...

随机推荐

  1. .Net 获取日期所属于一年中的第几周

    关键代码: public static int WeekOfYear(DateTime dt, CultureInfo ci) { //强制设置周一是每周的第一天 return ci.Calendar ...

  2. 面试01:解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法

    栈的使用:通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间. 队的使用:通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域 ...

  3. 64位Redhat系统应用(c++代码)搭建-使用informix和g++编译

    这篇博客很有必要写下来,记录我在一个比较原生的Linux系统上搭建一套应用所遇到的各种问题和各种坑. 关于这套应用,算是我离职前的一个项目,不完成的话没有办法交差,同时,这个项目也比较紧,合作行一直在 ...

  4. WPF 凭证分录控件

    凭证分录编辑控件,效果如下: 源码:https://gitee.com/orchis/VoucherGridCtl.git

  5. OpenCV-可视化界面Image Watch

    平台:Win10 x64+vs2015专业版+opencv-3.4.1-vc14_vc15 一直觉得OpenCV在调试方面不如MATLAB灵活方便,没成想OpenCV官方早就推出了一个叫Image W ...

  6. Awesome Python 中文版

    Awesome Python ,这又是一个 Awesome XXX 系列的资源整理,由 vinta 发起和维护.内容包括:Web框架.网络爬虫.网络内容提取.模板引擎.数据库.数据可视化.图片处理.文 ...

  7. SGTtrick

    SGTtrick By 蒟蒻 ldxoiBy\ 蒟蒻\ ldxoiBy 蒟蒻 ldxoi Chapter 1.关于线段树操作的一些分析 我们知道,线段树有两个核心的函数pushdownpushdown ...

  8. ZOJ 3229 Shoot the Bullet (有源有汇有上下界最大流)

    题意:一个人要给女孩子们拍照,一共 n 天,m 个女孩子,每天他至多拍 d[i] 张照片,每个女孩子总共要被至少拍 g[i] 次.在第 i 天,可以拍 c[i] 个女孩子,c[i] 个女孩子中每个女孩 ...

  9. CSS样式总结(作业六)

    1:CSS基本介绍 CSS全称为“层叠样式表 (Cascading Style Sheets)”,它主要是用于定义HTML内容在浏览器内的显示样式,如文字大小.颜色.字体加粗等. css 样式由选择符 ...

  10. pwm互补输出 死区设置

    void TIM8_PWM_Init(u16 arr,u16 psc){       GPIO_InitTypeDef GPIO_InitStructure;    TIM_TimeBaseInitT ...