有段时间没有写博客了,不知道是因为工作的原因还是懒了...
程序员还得以写代码为生,so~进入主题吧
公司是做广告服务的,运转模式一句话就是:在车内设备上播放广告主投放的广告,并获取收益,现在有个需求是,要统计广告主投放的广告里面的二维码的扫码量,进行数据分析,为后面人物画像做准备,因多种事业环境因素,让广告主提供统计数据或者提供链接给我们,我们生成二维码等,根本不太可能,所以,只能自己撸启袖子干!
我疏导了下流程,如下:
1.广告审核的时候,判断图片是否包含二维码
2.包含二维码的图片,对原图片里面二维码进行识别并定位
3.获取原图片里二维码的信息和坐标信息(x,y,w,h),并保存起来
4.开发一个接口,这个接口可以理解为新二维码的链接路径
5.根据坐标使用上面接口如(www.abc?taskId=10&imei=2ej3dd)生成新二维码并推送到设备
6.设备获取推送的包含二维码的图片并根据后台分发的坐标信息生成新的二维码
7.设备根据坐标和其他需要携带的参数生成新二维码
8.用户扫码跳转到接口路径,接口获得相关参数记录扫码量并重定向到原图片里面二维码路径
至此,大功告成!
一个东西的技术实现,都是站在前人的肩膀上去累积,优化,总结的,我大概在网上看了下,貌似没有人遇到这种需求,参考了opencv java版本的代码,毕竟不是做图像识别的,这方面的知识有限,所以用了zxing实现.于是自己硬着头皮上,基本实现了我们的业务需求,但,二维码的坐标识别还是有些许的差别,还是把代码分享出来,起抛砖引玉的作用,同时,也希望大家能够在这个基础上进行优化...
以下为代码片段
先加入maven依赖:
<!-- 二维码依赖 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.3</version>
</dependency>
下面为完整java代码:
package com.bpb.qrcode;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.imageio.ImageIO;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class QRCodeTools3 {
/**
*
* @Title: deEncodeByPath
* @Description: 替换原图片里面的二维码
* @param @param filePath
* @param @param newPath 设定文件
* @return void 返回类型
* @throws
*/
public static void deEncodeByPath(String filePath, String newPath) {
// 原图里面二维码的url
String originalURL = null;
try {
// 将远程文件转换为流
BufferedImage readImage = ImageIO.read(new File(filePath));
LuminanceSource source = new BufferedImageLuminanceSource(readImage);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result result = null;
result = new MultiFormatReader().decode(binaryBitmap, hints);
originalURL = result.getText();
// 解码
ResultPoint[] resultPoint = result.getResultPoints();
System.out.println("原二维码里面的url:" + originalURL + ",\npoints1: " + resultPoint[0] + ",\npoints2: " + resultPoint[1] + ",\npoints2: "
+ resultPoint[2] + ",\npoints2: " + resultPoint[3]);
// 获得二维码坐标
float point1X = resultPoint[0].getX();
float point1Y = resultPoint[0].getY();
float point2X = resultPoint[1].getX();
float point2Y = resultPoint[1].getY();
// 替换二维码的图片文件路径
BufferedImage writeFile = ImageIO.read(new File(newPath));
// 宽高
final int w = (int) Math
.sqrt(Math.abs(point1X - point2X) * Math.abs(point1X - point2X) + Math.abs(point1Y - point2Y) * Math.abs(point1Y - point2Y))
+ 12 * (7 - 1);
final int h = w;
Hashtable<EncodeHintType, Object> hints2 = new Hashtable<EncodeHintType, Object>();
hints2.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints2.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints2.put(EncodeHintType.MARGIN, 1);
Graphics2D graphics = readImage.createGraphics();
//此处,偏移,会有定位问题
int x = Math.round(point1X) - 36;
int y = Math.round(point2Y) - 36;
// 开始合并绘制图片
graphics.drawImage(writeFile, x, y, w, h, null);
// logo边框大小
graphics.setStroke(new BasicStroke(2));
// //logo边框颜色
graphics.setColor(Color.WHITE);
graphics.drawRect(x, y, w, h);
readImage.flush();
graphics.dispose();
// 打印替换后的图片
NewImageUtils.generateWaterFile(readImage, "F:\\image\\save.jpg");
}
catch (IOException e) {
log.error("资源读取失败" + e.getMessage());
e.printStackTrace();
}
catch (NotFoundException e) {
log.error("读取图片二维码坐标前发生异常:" + e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
deEncodeByPath("F:\\image\\zfb.jpg", "F:\\image\\gzh.jpg");
}
}
图一是替换之前的二维码图片(支付宝扫码领红包):
图二为需要替换原图二维码的图片(微信公众号)
当然,这也只是个雏形,有更好的方式的同学,可以留言一起探讨,并改善...
————————————————
版权声明:本文为CSDN博主「转瞬忆倾城」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012891290/article/details/86582687