python图像处理-形状提取和识别2(棋盘图像转为矩阵)

python图像处理-形状提取和识别2

(棋盘图像转为矩阵)
本系列一个分为两大部分:一个是形状提取,一个是形状识别
1.形状提取中,基于Hough函数法进行直线提取和圆形提取,还有即基于颜色的形状提取
这里扩展了一个小程序(识别一张棋盘图片,利用角点检测得到棋盘参数,再利用形状提取得到棋子位置,将棋盘图片转换成矩阵,再利用棋子圆心的RGB识别,用矩阵中的1表示黑子,0表示白子。“后面会把这个小扩展单独写出来玩”)
2.形状识别里用了几个OPEN-CV的函数


第一部分:形状提取

第二部分:扩展-棋盘转换为矩阵

这一部分的灵感是想到阿尔法狗如果是在实际棋盘上下棋,该如何将识别的图片转换为矩阵,再进行后面的公式运算。
第一步用到hough计算先计算出棋子圆心的坐标;第二步利用上周的harris角点对棋盘提取其边缘信息,得到棋盘四个边缘位置的坐标,以及每格间隔的距离。得到棋子中心坐标和棋盘边缘参数和格子间隔后,第三步是将其转换为矩阵表达;第四步是检测每个棋子的中心位置的RGB值,判断是黑棋子还是白棋子,黑棋子矩阵显示1,白棋子显示2,无棋子显示0,得到19*19棋盘情况的矩阵表示,用其他棋盘测试结果也成立。

第一步:利用形状检测捕捉棋子

检测到棋子,并得到棋子圆心坐标

qipan = cv2.imread('qipan.jpg',1)
qipan = cv2.cvtColor(qipan, cv2.COLOR_BGR2RGB)  
gray = cv2.cvtColor(qipan, cv2.COLOR_BGR2GRAY) 
edges = cv2.Canny(gray,100,200,apertureSize = 3)
plt.figure(figsize=(30, 20)); 
plt.subplot(121), plt.imshow(qipan)
plt.title('img'), plt.xticks([]), plt.yticks([])
circle1 = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=100, param2=24, minRadius=5, maxRadius=25)  
circles = circle1[0, :, :]  # 提取为二维
circles = np.uint16(np.around(circles))  # 四舍五入,取整
for i in circles[:]:
    cv2.circle(qipan, (i[0], i[1]), i[2], (255, 0, 0), 5)  # 画圆
#     cv2.circle(qipan, (i[0], i[1]), 1, (255, 0, 0), 10)  # 画圆心
plt.subplot(122), plt.imshow(qipan)
plt.title('circle'), plt.xticks([]), plt.yticks([]);

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

第二步:进行角点检测,得到棋盘参数

img_c1=cv2.imread('D:/classofmathpicture/qipan.jpg',0)
img_c1_CC=cv2.imread('D:/classofmathpicture/qipan.jpg',1)
img_c1_CC=cv2.cvtColor(img_c1_CC,cv2.COLOR_BGR2RGB)
Harris_c1 = cv2.cornerHarris(img_c1, 3, 3, 0.04)
dst_c1 = cv2.dilate(Harris_c1, None)  #将可以标出来的点粗化
plt.figure(figsize=(10, 10));
img_c1_C=img_c1_CC.copy()
thres = 0.1*dst_c1.max()
img_c1_C[dst_c1 > thres] = [255,0,0]
plt.imshow(img_c1_C)
# 从一幅Harris响应图像中返回角点,min_dist为分割角点和图像边界的最少像素数目
def get_harris_points(harrisim,min_dist=10,threshold=0.1):   
    # 寻找高于阈值的候选角点
    corner_threshold = harrisim.max() * threshold
    harrisim_t = (harrisim > corner_threshold) * 1  
    # 得到候选点的坐标
    coords = array(harrisim_t.nonzero()).T  
    # 以及它们的 Harris 响应值
    candidate_values = [harrisim[c[0],c[1]] for c in coords]   
    # 对候选点按照 Harris 响应值进行排序
    index = argsort(candidate_values)[::-1] 
    # 将可行点的位置保存到数组中
    allowed_locations = zeros(harrisim.shape)
    allowed_locations[min_dist:-min_dist,min_dist:-min_dist] = 1    
    # 按照 min_distance 原则,选择最佳 Harris 点
    filtered_coords = []
    for i in index:
        if allowed_locations[coords[i,0],coords[i,1]] == 1:
            filtered_coords.append(coords[i])
            allowed_locations[(coords[i,0]-min_dist):(coords[i,0]+min_dist), 
                        (coords[i,1]-min_dist):(coords[i,1]+min_dist)] = 0    
    return filtered_coords

from pylab import *
from numpy import *
wid=9   #比较像素点数目
filtered_coords1 = get_harris_points(dst_c1, wid+1,0.1)   #图1大于阈值的坐标

maxx=0
for i in range(len(filtered_coords1)):
    if filtered_coords1[i][0]>maxx:
        maxx=filtered_coords1[i][0]
maxy=0
for i in range(len(filtered_coords1)):
    if filtered_coords1[i][1]>maxy:
        maxy=filtered_coords1[i][1]
minx=maxx
for i in range(len(filtered_coords1)):
    if filtered_coords1[i][0]<minx:
        minx=filtered_coords1[i][0]
miny=maxy
for i in range(len(filtered_coords1)):
    if filtered_coords1[i][1]<miny:
        miny=filtered_coords1[i][1]
lensx=np.uint16(np.around((maxx-minx)/18))
lensy=np.uint16(np.around((maxy-miny)/18))

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

第三步:棋盘图片转换为矩阵

pan=np.zeros((19,19),int)
for n in range(len(circles[:,0])):
    x=np.uint16(np.around((circles[n,0]-minx)/lensx))
    y=np.uint16(np.around((circles[n,1]-miny)/lensy))
    pan[y,x]=1
pan

在这里插入图片描述
可以和上面的棋盘对应,发现到这一步是成功的

第四步:分出黑白棋子

黑棋子在矩阵中用1表示,白棋子用2,若无棋子用0表示

qipan = cv2.imread('D:/classofmathpicture/qipan.jpg',1)
qipan = cv2.cvtColor(qipan, cv2.COLOR_BGR2RGB)  
for n in range(len(circles[:,0])):
    j=circles[n,0]
    i=circles[n,1]
    x=np.uint16(np.around((circles[n,0]-minx)/lensx))
    y=np.uint16(np.around((circles[n,1]-miny)/lensy))
    avg=(int(qipan[i,j,0]) + int(qipan[i,j,1])+ int(qipan[i,j,2]))/3;
    if qipan[i,j,0] > 190:
        pan[y,x]=2
plt.imshow(qipan)
pan    

在这里插入图片描述

第三部分:形状识别

形状识别有篇博客不错,这里记载一下:
形状识别
下面用了他的函数也很好用👇

def getContours(img):
    # 查找轮廓,cv2.RETR_ExTERNAL=获取外部轮廓点, CHAIN_APPROX_NONE = 得到所有的像素点
    contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    # 循环轮廓,判断每一个形状
    for cnt in contours:
        # 获取轮廓面积
        area = cv2.contourArea(cnt)
        # 当面积大于500,代表有形状存在
        if area > 500:
            # 绘制所有的轮廓并显示出来
            cv2.drawContours(imgContour, cnt, -1, (0, 0, 0), 3)
            # 计算所有轮廓的周长,便于做多边形拟合
            peri = cv2.arcLength(cnt, True)
            # 多边形拟合,获取每个形状的边数目
            approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
            objCor = len(approx)
            # 获取每个形状的左上角坐标xy和形状的长宽wh
            x, y, w, h = cv2.boundingRect(approx)
            # 计算出边界后,即边数代表形状,如三角形边数=3
            if objCor == 3:
                objectType = "Tri"
            # 计算出边界后,即边数代表形状,如四边形边数=4
            elif objCor == 4:
                # 判断是矩形还是正方形
                aspRatio = w / float(h)
                if aspRatio > 0.98 and aspRatio < 1.03:
                    objectType = "Square"
                else:
                    objectType = "Rectangle"
            # 大于4个边的就是圆形
            elif objCor > 4:
                objectType = "Circles"
            else:
                objectType = "None"
            # 绘制文本时需要绘制在图形附件
            cv2.rectangle(imgContour, (x, y), (x + w, y + h), (255, 0, 0), 2)
            cv2.putText(imgContour, objectType,
                        (x + (w // 2) - 10, y + (h // 2) - 10), cv2.FONT_HERSHEY_COMPLEX, 0.7,
                        (0, 0, 0), 2)

path = 'D:/classofmathpicture/week4_shibie2.png'
img = cv2.imread(path)
imgContour = img.copy()

# 灰度化
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯平滑
imgBlur = cv2.GaussianBlur(imgGray, (7, 7), 1)
# 边缘检测
imgCanny = cv2.Canny(imgBlur, 50, 50)
# 获取轮廓特征点
getContours(imgCanny)

plt.figure(figsize=(30, 20));
plt.subplot(231);plt.imshow(img);plt.title('img');plt.axis('off');
plt.subplot(232);plt.imshow(imgGray,cmap='gray');plt.title('imgGray');plt.axis('off');
plt.subplot(233);plt.imshow(imgBlur,cmap='gray');plt.title('imgBlur');plt.axis('off');
plt.subplot(234);plt.imshow(imgCanny,cmap='gray');plt.title('imgCanny');plt.axis('off');
plt.subplot(235);plt.imshow(imgContour);plt.title('imgContour');plt.axis('off');

在这里插入图片描述

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值