JAVA方法:可以设置替换图片中原有二维码的图片,生成或覆盖原来的图片。
上代码:
QRCodeTools.java
/**
* @author SongBin on 2019/10/31.
*/
package com.wylc.eshop.common.utils.qrcode;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import java.awt.*;
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;
public class QRCodeTools {
/**
*
* @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] + ",\npoints3: "
+ resultPoint[2]);
// 获得二维码坐标
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\\zfb.png");
}
catch (IOException e) {
System.out.println("资源读取失败" + e.getMessage());
e.printStackTrace();
}
catch (NotFoundException e) {
System.out.println("读取图片二维码坐标前发生异常:" + e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
deEncodeByPath("F:\\image\\zfb.png", "F:\\image\\gzh.jpg");
}
}
NewImageUtils.java
/**
* @author SongBin on 2019/10/31.
*/
package com.wylc.eshop.common.utils.qrcode;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class NewImageUtils {
/**
*
* @Title: 构造图片
* @Description: 生成水印并返回java.awt.image.BufferedImage
* @param file
* 源文件(图片)
* @param waterFile
* 水印文件(图片)
* @param x
* 距离右下角的X偏移量
* @param y
* 距离右下角的Y偏移量
* @param alpha
* 透明度, 选择值从0.0~1.0: 完全透明~完全不透明
* @return BufferedImage
* @throws IOException
*/
public static BufferedImage watermark(File file, File waterFile, int x, int y, float alpha) throws IOException {
// 获取底图
BufferedImage buffImg = ImageIO.read(file);
// 获取层图
BufferedImage waterImg = ImageIO.read(waterFile);
// 创建Graphics2D对象,用在底图对象上绘图
Graphics2D g2d = buffImg.createGraphics();
int waterImgWidth = waterImg.getWidth();// 获取层图的宽度
int waterImgHeight = waterImg.getHeight();// 获取层图的高度
// 在图形和图像中实现混合和透明效果
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
// 绘制
g2d.drawImage(waterImg, x, y, waterImgWidth, waterImgHeight, null);
g2d.dispose();// 释放图形上下文使用的系统资源
return buffImg;
}
/**
* 输出水印图片
*
* @param buffImg
* 图像加水印之后的BufferedImage对象
* @param savePath
* 图像加水印之后的保存路径
*/
public static void generateWaterFile(BufferedImage buffImg, String savePath) {
int temp = savePath.lastIndexOf(".") + 1;
try {
ImageIO.write(buffImg, savePath.substring(temp), new File(savePath));
} catch (IOException e1) {
e1.printStackTrace();
}
}
/**
*
* @param args
* @throws IOException
* IO异常直接抛出了
* @author bls
*/
public static void main(String[] args) throws IOException {
String sourceFilePath = "D://img//di.png";
String waterFilePath = "D://img//ceng.png";
String saveFilePath = "D://img//new.png";
NewImageUtils newImageUtils = new NewImageUtils();
// 构建叠加层
BufferedImage buffImg = NewImageUtils.watermark(new File(sourceFilePath), new File(waterFilePath), 0, 0, 1.0f);
// 输出水印图片
newImageUtils.generateWaterFile(buffImg, saveFilePath);
}
}
Python方法:提供logo图片根据原来的二维码解析内容,结合新logo图片生成新的二维码覆盖原来的二维码。
上代码:
#!/usr/bin/env python
# _*_coding:utf-8_*_
__author__ = 'Jun'
__time__ = '2019/4/25 10:48'
#识别图片中的二维码,并对二维码进行替换,经过多次验证,识别率极高,替换效果很好,特分享出来,供需要的兄弟参考
import pyzbar.pyzbar as pyzbar
import numpy as np
import cv2
import qrcode
from PIL import Image
import urllib.request
# 生成新的二维码图片并覆盖原图
def detect(im, save_path=None):
# 解析图片中的二维码内容
results = pyzbar.decode(im)
points = []
# 获取所有解析对象
for code in results:
points = code.polygon
# 如果这些点不形成四边形,则找到一个
if len(points) > 4:
hull = cv2.convexHull(np.array([point for point in points], dtype=np.float32))
hull = list(map(tuple, np.squeeze(hull)))
else:
hull = points
# 将cv2对象转换为Image对象
img = Image.fromarray(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
# 若二维码解析成功,则生成新的二维码并覆盖
if hull:
# 获取二维码解析数据
data = results[0].data.decode("utf-8")
if data:
width = results[0].rect.width + 2
height = results[0].rect.height + 2
left = results[0].rect.left - 1
top = results[0].rect.top - 1
# 生成带中心图标的二维码 data为原来的二维码数据,可以替换为自己的数据
qr_code_img = make_qr_code_with_icon(data, 'F:/image/log.jpg')
# 设置二维码的尺寸
qr_code_img = qr_code_img.resize((width, height), Image.ANTIALIAS)
# 将原图上的二维码替换为新的二维码
img.paste(qr_code_img, (left,top))
# 保存新生成的图片
if save_path:
img.save(save_path)
# 显示原图和新生成的图片
img.show()
cv2.imshow('imshow', im)
cv2.waitKey(0)
cv2.destroyAllWindows()
return save_path
# 生成新的带中心logo的二维码图片
def make_qr_code_with_icon(content, icon_path):
# 生成一张二维码图片
qr_code_maker = qrcode.QRCode(version=5,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=0,
)
qr_code_maker.add_data(data=content)
qr_code_maker.make(fit=True)
qr_code_img = qr_code_maker.make_image(fill_color="black", back_color="white").convert('RGBA')
# 加载中心图标,设置大小
icon_img = Image.open(icon_path)
code_width, code_height = qr_code_img.size
icon_img = icon_img.resize((code_width // 4, code_height // 4), Image.ANTIALIAS)
# 将图标放置于原始图片上
qr_code_img.paste(icon_img, (code_width * 3 // 8, code_width * 3 // 8))
return qr_code_img;
# 根据图片路径获取cv2对象
def get_cv2_image(img_path):
image = None
if img_path.startswith('http:') or img_path.startswith('https:'):
# 从网络路径加载图片资源
resp = urllib.request.urlopen(img_path)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
else:
# 从本地获取图片资源
image = cv2.imread(img_path)
return image
if __name__ == '__main__':
# img_path = 'https://bpb-test.oss-cn-beijing.aliyuncs.com/test/1.jpg?OSSAccessKeyId=LTAIBGsGFQH2Kxns&Expires=1555700356&Signature=%2FgLKrl4Fyjko%2FD97OmJGHlYea3s%3D'
img_path = 'F:/image/zfb1.jpg'
image = get_cv2_image(img_path)
detect(image)
更多内容请访问:IT源点
注意:本文归作者所有,未经作者允许,不得转载