花了2天时间终于把二维码识别做出来了,不过效果一般,后面会应用在ROS辅助定位上,废话少说先上图:
具体过程参考了这位大神的博客:http://blog.csdn.net/qq_25491201/article/details/51065547
详细解释:
第一步:利用opencv提取二维码区域
1,先将读入的摄像头frame转换成灰度图:
gray = cv2.cvtColor(image_path, cv2.COLOR_BGR2GRAY)
2,使用opencv自带的Sobel算子进行过滤:
gradX = cv2.Sobel(gray, cv2.CV_32F, 1, 0,-1)
gradY = cv2.Sobel(gray, cv2.CV_32F, 0, 1,-1)
具体参数可参考:http://blog.csdn.net/sunny2038/article/details/9170013
3,将过滤得到的X方向像素值减去Y方向的像素值:
gradient = cv2.subtract(gradX, gradY)
4,先缩放元素再取绝对值,最后转换格式为8bit型
gradient = cv2.convertScaleAbs(gradient)
5,均值滤波取二值化:
blurred = cv2.blur(gradient, (9, 9))
(_, thresh) = cv2.threshold(blurred, 160, 160, cv2.THRESH_BINARY)
6,腐蚀和膨胀的函数:
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)
7,找到边界findContours函数
binary,cnts,hierarchy = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
8,计算出包围目标的最小矩形区域:
c = sorted(cnts, key = cv2.contourArea, reverse = True)[0]
rect = cv2.minAreaRect(c)
box = np.int0(cv2.boxPoints(rect))
第二步:识别二维码
关于识别那就比较简单了,主要是加载import zbar库,然后scan就好了。
cap = cv2.VideoCapture(camera_idx)
# create a reader
scanner = zbar.ImageScanner()
# configure the reader
scanner.parse_config(\'enable\')
box = detect.detect(frame)
if box != None:
# 这下面的3步得到扫描区域,扫描区域要比检测出来的位置要大
min = np.min(box, axis=0)
max = np.max(box, axis=0)
roi = frame[min[1] - 10:max[1] + 10, min[0] - 10:max[0] + 10]
print roi.shape
# 把区域里的二维码传换成RGB,并把它转换成pil里面的图像,因为zbar得调用pil里面的图像,而不能用opencv的图像
roi = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB)
pil = Image.fromarray(frame).convert(\'L\')
width, height = pil.size
raw = pil.tostring()
# 把图像装换成数据
zarimage = zbar.Image(width, height, \'Y800\', raw)
# 扫描器进行扫描
scanner.scan(zarimage)