首先看一下我的验证码类型,此款验证码看似非常的简单,背景单一,没有太多的噪音,加上灰度滑块也比较清晰,所以直接用opencv中的边缘检测加上轮廓提取轻易就能实现,但其实,我们用cv2读取图片会发现暗藏玄机。
首先,有意思的是,我们直接用cv2读取图片后,在展示出来,是这样的
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import os
img = cv2.imread(r"1.png")
def cv_show(img): # 展示图片
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv_show(img)
为什么展示出来是个缺口呢,其实是因为这种本身是4个通道的,也就是RGBA,这种滑块的缺口的原理就是,一副完整的RGB图像加上一小块的透明通道图像,使得图像一块区域,呈现出透明状态,就像了滑块缺口一样
那么这种情况就更好处理了,直接把透明通道取出来,利用边缘检测+轮廓提取,这样得出来的结果还会非常精准
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import os
img = cv2.imread(r"3.png",cv2.IMREAD_UNCHANGED)
def cv_show(img): # 展示图片
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
BGRA = cv2.split(img)
BGRA[0][BGRA[3] != 255] = 0
BGRA[1][BGRA[3] != 255] = 0
BGRA[2][BGRA[3] != 255] = 0
result = cv2.merge([BGRA[0], BGRA[1], BGRA[2]])
v1 = cv2.Canny(BGRA[3], 20, 200) # 边缘检测, 20和80分别为两个阈值
cv_show(v1)
counts, _ = cv2.findContours(v1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 轮廓检测
color = (0, 255, 0)
for c in counts:
area = cv2.contourArea(c, True)
x, y, w, h = cv2.boundingRect(c) # 计算x,y,宽,高
if w < 30: continue # 去掉太小的轮廓
if h < 30: continue # 去掉太小的轮廓
print(x, y, w, h)
# print(area)
# if w > 55 or w < 30 or h > 55 or h < 30:
# continue
img = cv2.rectangle(img, (x, y), (x + w, y + h), color, 2) # 画出矩形框
result = cv2.rectangle(result, (x, y), (x + w, y + h), color, 2) # 画出矩形框
cv_show(img)
cv_show(result)
通过运行代码可以看到,首先展示的是透明通道的边缘检测效果,效果很好,然后在展示的图片中画出该轮廓,最后,对原图稍加处理,把透明通道的区域全部填充为0,再画图轮廓,即为最后一张图的效果