草庐IT

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

小草莓爸爸 2024-05-23 原文

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');

有关python图像处理-形状提取和识别2(棋盘图像转为矩阵)的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  3. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  4. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  5. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  6. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  7. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  8. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  9. [Vuforia]二.3D物体识别 - 2

    之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶

  10. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

随机推荐