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通道顺序
看一下结果:
Opencv边缘检测破解滑动验证码基于python(透明通道)_第1张图片

图像增强

这里图像增强的方式是通过观察缺口都处于阴影所以该位置通道值要小于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

Opencv边缘检测破解滑动验证码基于python(透明通道)_第2张图片
此时可以看出缺口位置非常明显。

边缘检测+轮廓提取

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

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

结果:
Opencv边缘检测破解滑动验证码基于python(透明通道)_第3张图片
此时可以看出轮廓非常清晰了。只需要进行轮廓提取就可以了。

 	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}")

边缘检测出来的轮廓肯定有很多种我们不需要的将其通过宽和高过滤掉即可。
如果不过滤呈现的是:
Opencv边缘检测破解滑动验证码基于python(透明通道)_第4张图片
将其过滤后:
Opencv边缘检测破解滑动验证码基于python(透明通道)_第5张图片
得到坐标
左上点的坐标为:(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

透明通道问题

Opencv边缘检测破解滑动验证码基于python(透明通道)_第6张图片
Opencv边缘检测破解滑动验证码基于python(透明通道)_第7张图片

类似于这种图片我们肉眼看到的缺口计算机是看不到的,原因是该图片存在透明通道,也就是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通道转为黑色
得到的结果为:
在这里插入图片描述
之后就和上面一样进行边缘检测,轮廓提取之后再找到缺口位置。

结果展示

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

你可能感兴趣的:(图像处理,opencv)