【实战】二维码替换的小故事,附源码

一、前言

上次的文章告诉大家制作自己独有的二维码这个码,妙不可言!,今天分享一下如何像我一样制作一个海报,替换海报上的二维码。

地址:https://blog.csdn.net/qq_36441393/article/details/111411608

当时这个想法是这样来的:业主群里每天早上都有物业人员分享一副海报,我觉得海报挺让人赏心悦目的,我如果分享到朋友圈也挺不错,但是海报上面有个物业公司的二维码,我想何不换成我的二维码试试。(我知道美图秀秀等软件可以做到,但是技术人就是不一样,非要折腾!)

图片

来自物业的海报

 

二、方法

我们技术人换二维码怎么换呢?

我们理一下思路,如果我们替换这个二维码,用手机P图软件该是什么思路,我们的步骤应该是这样:

1、找到原图二维码的位置。

2、缩放将要覆盖的二维码大小。

3、粘贴到原图二维码位置。

好的,技术人已经知道该怎么做了。

首先找二维码,利用python的opencv库来实现即可。这个二维码出现的位置很突出,在右下角,那我们完全可以通过找图中的轮廓,然后得到最右下角的轮廓位置即可,分别得到二维码的起始坐标点和尺寸宽高。代码参考如下。

import cv2

#==========获得二维码起始坐标位置和尺寸大小==
def find_code(pic_file):
    # print("请输入解码图片完整名称:")
    # code_name = input('>>:').strip()
    # print("正在识别:")
    image = cv2.imread(pic_file)
    # image = cv2.imread(code_name)
    # 灰度
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 使用opencv自带的Sobel算子进行过滤
    gradX = cv2.Sobel(gray, ddepth=cv2.cv2.CV_32F, dx=1, dy=0, ksize=-1)
    gradY = cv2.Sobel(gray, ddepth=cv2.cv2.CV_32F, dx=0, dy=1, ksize=-1)

    # 将过滤得到的X方向像素值减去Y方向的像素值
    gradient = cv2.subtract(gradX, gradY)
    # 先缩放元素再取绝对值,最后转换格式为8bit型
    gradient = cv2.convertScaleAbs(gradient)
    # 均值滤波取二值化
    blurred = cv2.blur(gradient, (9, 9))
    (_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)

    # 腐蚀和膨胀的函数
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
    closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
    closed = cv2.erode(closed, None, iterations=4)
    closed = cv2.dilate(closed, None, iterations=4)
    cv2.imwrite('./pic/closed.jpg', closed)
    # 找到边界findContours函数
    (_, cnts, _) = cv2.findContours(closed.copy(),
                                    cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    print(cnts,type(cnts))
    a =cnts
    print(a,type(a),len(a))
    # 计算出包围目标的最小矩形区域
    c = sorted(cnts, key=cv2.contourArea, reverse=False)[0]

    tmp =0
    max =0
    len(a)
    for i in range(len(a)):

        xy =a[i][-1][0][0] + a[i][-1][0][1]
        if  xy >max:
            max =xy
            tmp= i
        # print(a[i][0][0],a[i][0][1])
    # print(tmp)
    # print(a[tmp])
    rect = cv2.minAreaRect(c)
    rect1 = cv2.minAreaRect(a[tmp])
    # print(rect,rect1)
    box = np.int0(cv2.boxPoints(rect1))
    print(box)
    #======显示=======
    # windowname ="ScanQRcodeTest"
    # cv2.namedWindow(windowname, cv2.WINDOW_NORMAL)
    # cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
    # cv2.imshow(windowname, image)
    # cv2.waitKey(0)
    #===============

    #=========保存证据=======
    # 绘制轮廓
    cv2.drawContours(image, [box], -1, (0, 255, 0), 3)

    cv2.imwrite('./pic/findresult.jpg',image)

    # ====获得二维码起始坐标位置和尺寸大小
    x0,y0 = box[1][0],box[1][1]
    x3,y3 =box[3][0],box[3][1]
    height = y3-y0
    width = x3 -x0
    return x0,y0 ,height,width

 

通过以上代码,我们能找到二维码框。下图绿色框出。

图片图片

预处理后找到二维码位置

 

好了,找到这个二维码位置,然后就该上我们自己的二维码了,之前有介绍过自己二维码的生成,这个码,妙不可言!。但是用之前需要把我们自己生成的二维码尺寸进行一个缩放,这样才能比较合适的覆盖上去。那尺寸依据原图上的二维码尺寸进行缩放。缩放后利用python的Image库的paste在原位置上进行覆盖。代码参考如下。


import qrcode

my_str ='https://mp.weixin.qq.com/s/jbEeVf8i9cm7yKaQP9SVoQ'
my_qrcode_filename ='./pic/simpleqrcode.jpg'
img = qrcode.make(my_str)
img.save(my_qrcode_filename)


#========找位置==========
pic_file ='./pic/pic1221.jpg'
x0,y0 ,height,width=find_code(pic_file)

#========对粘贴的二维码进行尺寸调整==========
img = cv2.imread(my_qrcode_filename)
img_copy = img.copy()
img_copy = cv2.resize(img_copy,(width+10,height+10))
cv2.imwrite('./pic/yudaresize.jpg',img_copy)


#=========粘贴新二维码===========
from PIL import Image
import matplotlib.pyplot as plt
img= Image.open(pic_file)
img2=Image.open(r'./pic/yudaresize.jpg')
img.paste(img2,(x0-5,y0-5,x0+width+5,y0+height+5))
# plt.imshow(img)
# plt.show()
img.save("./pic/newpic.jpg")

三、总结

这样基本就完成了所有任务,还算比较简单吧。

其中最为关键的是二维码的位置提取,目前只是基于这个物业公司的海报进行的匹配,若是复杂背景或可能需要在代码上做参数调整或逻辑上的调整。

当然做的更好的算法是用深度学习目标检测,这样需要我们进行一些标注,训练出一个合适的模型,有时间的朋友可以尝试。

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值