Opencv边缘检测破解滑动验证码基于python(透明通道)

边缘检测对于缺口明细的图形非常好用例如这种:
请添加图片描述
在或者是
请添加图片描述
两种都是缺口边缘明显,只要稍加处理就可以得到轮廓边缘
直接开搞

读取文件

 # 读取文件
  image = Image.open(path)
  img = image.copy()  # 复制
  img = np.array(img)  # 转化为numpy
  img = cv2.resize(img, (268, 100))  # 用cv2resize
  img = img[:, :, (2, 1, 0)]  #RGB BGR图像

这里用的 PIL的读取图片而不是opencv 因为我的图片路径存在中文名称用opencv的imread是读取不了的。 所以先用pil读取 再转化为numpy格式最后放到cv2.resize重组,注意一点是PIL读入图片默认通道顺序是RGB,接下来的操作要用cv所以转化为cv.show读取的BGR通道顺序
看一下结果:
在这里插入图片描述

图像增强

这里图像增强的方式是通过观察缺口都处于阴影所以该位置通道值要小于150的区域变为黑色,否则转为白色,方便为后续的边缘检测做铺垫

# 将通道值小于150的转变为黑色 
    for h in range(img.shape[0]):
        for w in range(img.shape[1]):
            if img[h, w, 0] < 150 and img[h, w, 1] < 150 and img[h, w, 2] < 150:
                for c in range(3):
                    img[h, w, c] = 0
            else:
                for c in range(3):
                    img[h, w, c] = 255

在这里插入图片描述
此时可以看出缺口位置非常明显。

边缘检测+轮廓提取

直接使用canny算法进行轮廓提取

canny_img = cv2.Canny(img, 0, 100)  # 边缘检测

结果:
在这里插入图片描述
此时可以看出轮廓非常清晰了。只需要进行轮廓提取就可以了。

 	counts, _ = cv2.findContours(canny_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # 轮廓检测
    for c in counts:
        x, y, w, h = cv2.boundingRect(c)
        #  去除较小先验框
        if w < 20:
            continue
        if h < 20:
            continue
        cv2.rectangle(img1, (x, y), (x + w, y + h), (0, 0, 255), 2)
        print(f"左上点的坐标为:{x, y},右下点的坐标为{x + w, y + h}")

边缘检测出来的轮廓肯定有很多种我们不需要的将其通过宽和高过滤掉即可。
如果不过滤呈现的是:
在这里插入图片描述
将其过滤后:
在这里插入图片描述
得到坐标
左上点的坐标为:(190, 44),右下点的坐标为(222, 76)

完整代码

def hk(path):
    # 读取文件
    image = Image.open(path)
    img = image.copy()  # 复制
    img = np.array(img)  # 转化为numpy
    img = cv2.resize(img, (268, 100))  # 用cv2resize
    img = img[:, :, (2, 1, 0)]  # BGR图像转RGB
    img1 = img.copy()
    # 将通道值小于150的转变为黑色
    for h in range(img.shape[0]):
        for w in range(img.shape[1]):
            if img[h, w, 0] < 150 and img[h, w, 1] < 150 and img[h, w, 2] < 150:
                for c in range(3):
                    img[h, w, c] = 0
            else:
                for c in range(3):
                    img[h, w, c] = 255
    canny_img = cv2.Canny(img, 0, 100)  # 边缘检测
    counts, _ = cv2.findContours(canny_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # 轮廓检测
    for c in counts:
        x, y, w, h = cv2.boundingRect(c)
        #  去除较小先验框
        if w < 20:
            continue
        if h < 20:
            continue
        cv2.rectangle(img1, (x, y), (x + w, y + h), (0, 0, 255), 2)
        print(f"左上点的坐标为:{x, y},右下点的坐标为{x + w, y + h}")
    return img1

透明通道问题

在这里插入图片描述
在这里插入图片描述

类似于这种图片我们肉眼看到的缺口计算机是看不到的,原因是该图片存在透明通道,也就是rgba。
解决此类型的图片思路就是 将透明通道区域的颜色变为对比度强的颜色如黑色,在进行边缘检测和轮廓提取。

我们用cv读取之后的样子是
在这里插入图片描述
那么缺口在哪里呢?

image = cv2.imread(path, -1)
cv2.imshow("image", image)
b, g, r, a = cv2.split(image)
b[a != 255] = 0
g[a != 255] = 0
r[a != 255] = 0
img = cv2.merge([b, g, r])
cv2.imshow("image", image)
``

 - [ ] List item

我们先将图片读取进来用imread -1的参数将全部通道读取进来
然后将其通道分割,将找到透明通道不等于255的位置,再将其bgr通道转为黑色
得到的结果为:
在这里插入图片描述
之后就和上面一样进行边缘检测,轮廓提取之后再找到缺口位置。

结果展示

在这里插入图片描述
在这里插入图片描述
此方法仅适用图像类型简单,缺口较为明显。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值