python opencv 轮廓检测,图像反色,形态学操作,分离通道

cv2.findContours()函数

函数的原型为

cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])
'''
返回两个值:contours:hierarchy。 
参数
第一个参数是寻找轮廓的图像;

第二个参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口):
    cv2.RETR_EXTERNAL表示只检测外轮廓
    cv2.RETR_LIST检测的轮廓不建立等级关系
    cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
    cv2.RETR_TREE建立一个等级树结构的轮廓。

第三个参数method为轮廓的近似办法
    cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
    cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
    cv2.CHAIN_APPROX_TC89_
'''
'''
返回值
cv2.findContours()函数返回两个值,一个是轮廓本身,还有一个是每条轮廓对应的属性。
contour返回值
cv2.findContours()函数首先返回一个list,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。这个概念非常重要。在下面drawContours中会看见。通过 
print (type(contours))
print (type(contours[0]))
print (len(contours))
可以验证上述信息。会看到本例中有两条轮廓,一个是五角星的,一个是矩形的。每个轮廓是一个ndarray,每个ndarray是轮廓上的点的集合。
由于我们知道返回的轮廓有两个,因此可通过
cv2.drawContours(img,contours,0,(0,0,255),3)
和
cv2.drawContours(img,contours,1,(0,255,0),3)
'''

轮廓的绘制

OpenCV中通过cv2.drawContours在图像上绘制轮廓。  

cv2.drawContours()函数

cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])

'''
第一个参数是指明在哪幅图像上绘制轮廓;
第二个参数是轮廓本身,在Python中是一个list。
第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。后面的参数很简单。其中thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。绘制参数将在以后独立详细介绍。
'''

 例子

'''
简单场景:形态学操作法
转灰度图,降噪二值化,多次膨胀(高亮部分扩张)腐蚀(高亮部分蚕食)突出轮廓消除边框线条,查找轮廓,返回文字检测边框
'''
import cv2
import numpy as np
imagepath = './data/13.jpg'
img = cv2.imread(imagepath)
w,h,c = img.shape
print('shape: ',img.shape)

imgcopy = img.copy()
# b, g, r = cv2.split(img)
# cv2.imshow("Blue 1", b)
# cv2.imshow("Green 1", g)
# cv2.imshow("Red 1", r)

img_gry = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print('shape: ',img_gry.shape)
cv2.imshow('img_gry',img_gry)

# sobel = cv2.Sobel(img_gry,cv2.CV_8U,1,0,ksize=3)
# cv2.imshow("sober",sobel)

guass = cv2.GaussianBlur(img_gry,(5,5),0)
cv2.imshow("guass",guass)
# 二值化,白底黑字
min, max, minLoc, maxLoc = cv2.minMaxLoc(guass)
print("min: %.2f, max: %.2f"% (min, max))
print("min loc: ", minLoc)
print("max loc: ", maxLoc)

means, stddev = cv2.meanStdDev(guass)
print("mean: %.2f, stddev: %.2f"% (means, stddev))
guass[np.where(guass < means)] = 0
guass[np.where(guass > means)] = 255
cv2.imshow("binary-白底黑字", guass)

# 二值化,黑底白字,图像反色
for row in range(h):
    for col in range(w):
        pv = guass[col,row]
        guass[col,row] = 255 - pv
cv2.imshow("binary-黑底白字", guass)


ret,binary1 = cv2.threshold(guass,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)
ret2,binary2 = cv2.threshold(guass,0,255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
ret3,binary3 = cv2.threshold(guass,0,255,cv2.THRESH_TRUNC + cv2.THRESH_OTSU)
ret4,binary4 = cv2.threshold(guass,0,255,cv2.THRESH_TOZERO + cv2.THRESH_OTSU)
ret5,binary5 = cv2.threshold(guass,0,255,cv2.THRESH_TOZERO_INV + cv2.THRESH_OTSU)
ret6,binary6 = cv2.threshold(guass,0,255,cv2.THRESH_TRIANGLE)

binary7 = cv2.adaptiveThreshold(guass,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)

# cv2.imshow('binary1',binary1)
# cv2.imshow('binary2',binary2)
# # cv2.imshow('binary3',binary3)
# cv2.imshow('binary4',binary4)
# cv2.imshow('binary5',binary5)
# cv2.imshow('binary6',binary6)
# cv2.imshow('binary7',binary7)
#cv2.imshow('binary-binary2',guass-binary2)


element1 = cv2.getStructuringElement(cv2.MORPH_CROSS,(11,11))
element2 = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
element3 = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))

dilation1 = cv2.dilate(guass,element1,iterations=2) # 膨胀
cv2.imshow('dilation1',dilation1)
cv2.imshow('dilation1-binary2',dilation1-binary2)

erosion1 = cv2.erode(dilation1, element2, iterations=3) # 腐蚀
cv2.imshow('erosion', erosion1)

dilation = cv2.dilate(erosion1,element2,iterations=2)
cv2.imshow('dilation',dilation)

erosion2 = cv2.erode(dilation,element2,iterations=1)
cv2.imshow('erosion2',erosion2)
cv2.imshow('dilation-erosion',dilation-erosion1)

#查找轮廓和筛选文字区域
region = []
rects = []
area_max = 0
contours,hierarchy = cv2.findContours(dilation,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
    print('len(contours)',len(contours))
    cnt = contours[i]
    # 计算轮廓面积,并筛选掉面积小的
    area = cv2.contourArea(cnt)
    print('area',area)
    if (area > area_max):
        area_max=area
        region.clear()
        rects.clear()
        #     continue
        # 获取最小外接矩阵,中心点坐标,宽高,旋转角度
        rect = cv2.minAreaRect(cnt)

        print("rect is:")
        print(rect)
        # 获取矩形四个顶点,浮点型
        box = cv2.boxPoints(rect)
        # 取整
        box = np.int64(box)

        left_point_x = np.min(box[:, 0])
        right_point_x = np.max(box[:, 0])
        top_point_y = np.min(box[:, 1])
        bottom_point_y = np.max(box[:, 1])

        # 计算高和宽
        height = abs(box[0][1] - box[2][1])
        width = abs(box[0][0] - box[2][0])
        # 跟据文字特征,筛选太细的矩形,留下扁的
        # if(height > width*1.3):
        #     continue
        region.append(box)
        rects.append(rect)
print('region',region)

# for rect in rects:
#     center_x_y = rect[0]
#     w = rect[1][0]
#     h = rect[1][1]
#     angle = rect[2]
#     # 左上
#     x1 = int(center_x_y[0]-w/2)
#     y1 = int(center_x_y[1]-h/2)
#     # 左下
#     x3 = int(center_x_y[0]-w/2)
#     y3 = int(center_x_y[1]+h/2)
#     # 右上
#     x2 = int(center_x_y[0]+w/2)
#     y2 = int(center_x_y[1]-h/2)
#     # 右下
#     x4 = int(center_x_y[0]+w/2)
#     y4 = int(center_x_y[1]+h/2)
#     rect_box = np.array([[x1, y1], [x3, y3], [x2, y2],
#                          [x4, y4]])
#     print('rect_box',rect_box)
#     cv2.rectangle(img,(x1,y1),(x4,y4),(0,255,0),2)
#     # imgcopy = guass[y1:y4,x1:x4]
#     # imgcopy = cv2.cvtColor(imgcopy,cv2.COLOR_GRAY2BGR)
#
#     # # 二值化,黑底白字
#     # for row in range(imgcopy.shape[1]):
#     #     for col in range(imgcopy.shape[0]):
#     #         pv = imgcopy[col, row]
#     #         imgcopy[col, row] = 255 - pv



# 绘制轮廓
for box in region:
    print('box',box)
    #center =
    # 获取四个顶点坐标
    left_point_x = np.min(box[:, 0])
    right_point_x = np.max(box[:, 0])
    top_point_y = np.min(box[:, 1])
    bottom_point_y = np.max(box[:, 1])

    left_point_y = box[:, 1][np.where(box[:, 0] == left_point_x)][0]
    right_point_y = box[:, 1][np.where(box[:, 0] == right_point_x)][0]
    top_point_x = box[:, 0][np.where(box[:, 1] == top_point_y)][0]
    bottom_point_x = box[:, 0][np.where(box[:, 1] == bottom_point_y)][0]
    # 上下左右四个点坐标
    vertices = np.array([[top_point_x, top_point_y], [bottom_point_x, bottom_point_y], [left_point_x, left_point_y],
                         [right_point_x, right_point_y]])
    print('vertices',vertices)
    cv2.drawContours(img,[box],0,(0,0,255),2)
    imgcopy = guass[top_point_y:bottom_point_y,left_point_x:right_point_x]
    # p1 = np.float32([[0, 0], [w-1 , 0], [0, h-1 ],[w-1,h-1]])
    # p2 = np.float32([[left_point_x, top_point_y], [right_point_x, top_point_y], [left_point_x, bottom_point_y],[right_point_x,bottom_point_y]])
    # M = cv2.getAffineTransform(p1, p2)
    # imgcopy = cv2.warpAffine(imgcopy, M, (w, h))

cv2.imshow('img',img)

cv2.imshow('imgcopy',imgcopy)
cv2.imwrite('./data/result.jpg',imgcopy)
cv2.waitKey(0)
cv2.destroyAllWindows()
 

 形态学操作-腐蚀与膨胀

 https://www.cnblogs.com/XJT2018/p/9958895.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值