今天柯洁开始对战AlphaGo,虽然对围棋一窍不通,但这种大事我也在关注,知道胜负与最后棋盘上黑白子的数量有关。当我看到结局的棋盘时,黑白棋子那么多,一时也看不出来谁多谁少,就想着编个程序来计算一下。程序很简单,就给大家分享一下,对OpenCV初学者或许有些帮助吧。

    先在网上找到了一个围棋图片,图片如下
由于黑白子颜色反差非常明显,只需要将原图转化为灰度图,再用合适的阈值进行二值化就可以。白子的灰度值都在200上以,我就以190为阈值就行二值化,黑子的灰度在80以下,便以90为阈值进行二值化。
     以190为阈值进行二值化后,图片变成下图这个样子
    这时画面噪点太多,我们需要腐蚀一下,用圆形算子对图片进行腐蚀,代码如下
IplConvKernel* elem = cvCreateStructuringElementEx(7, 7, 3, 3, CV_SHAPE_ELLIPSE);
cvErode(bw, bw, elem, 1);
cvReleaseStructuringElement(&elem);
腐蚀后的效果还是较为理想的,如下图所示
到了这一步,想必大家都知道下一步该怎么做了——直接找连通集,只要边缘点数满足条件,就可以计数为一个白子。相关代码如下
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage);
cvFindContours(bw, storage, &cont, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0, 0));
int white = 0;
float lowLimit = src->height / 50 * 3.1416;
float topLimit = src->height / 20 * 3.1416;
cout << lowLimit << '\t' << topLimit << endl;
for (; cont; cont = cont->h_next)
{int count = cont->total;if (count < lowLimit || count > topLimit)continue;white++;CvMoments mom;cvMoments(cont, &mom, true);CvPoint p;p.x = mom.m10 / mom.m00 - 5;p.y = mom.m01 / mom.m00 + 10;CvFont font = cvFont(0.7, 0.8);cvPutText(src, to_string(white).c_str(), p, &font, cvScalar(0, 0, 0));
}
cout << white << endl;
cvReleaseMemStorage(&storage);  
【备注一下】,程序中的lowLimittopLimit指的是边缘点数的上下限,边缘点数也就是周长的意思,所以乘以3.1416。只有该连通集的边缘点数在lowLimit和topLimit之间,才认为是白子;mom.m10 / mom.m00mom.m01 / mom.m00是求质心坐标,-5和+10是将打印的数字移到中心处。
黑子的计算方法是一样的,只不过二值化时,需使用关键字CV_THRESH_BINARY_INV。完成后,最终的效果图如下
完整的代码如下
#include <cv.h>
#include <highgui.h>
#include <iostream>
#include <string>
using namespace std;
#define THRESH1 190
#define THRESH2 100void showImg(IplImage* img, string str)
{cvNamedWindow(str.c_str(), CV_WINDOW_AUTOSIZE);cvShowImage(str.c_str(), img);
}int main()
{IplImage *src = cvLoadImage("E:/qipan.jpg");    IplImage* gray = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);   cvCvtColor(src, gray, CV_RGB2GRAY); IplImage* bw = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);//以下部分是计算白棋cvThreshold(gray, bw, THRESH1, 255, CV_THRESH_BINARY);    IplConvKernel* elem = cvCreateStructuringElementEx(7, 7, 3, 3, CV_SHAPE_ELLIPSE);cvErode(bw, bw, elem, 1);cvReleaseStructuringElement(&elem);/*showImg(bw, "二值化");*//*cvSaveImage("E:/result2.jpg", bw);*/CvMemStorage* storage = cvCreateMemStorage(0);CvSeq* cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage);cvFindContours(bw, storage, &cont, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0, 0));int white = 0;float lowLimit = src->height / 50 * 3.1416;float topLimit = src->height / 20 * 3.1416;cout << lowLimit << '\t' << topLimit << endl;for (; cont; cont = cont->h_next){int count = cont->total;if (count < lowLimit || count > topLimit)continue;white++;CvMoments mom;cvMoments(cont, &mom, true);CvPoint p;p.x = mom.m10 / mom.m00 - 5;p.y = mom.m01 / mom.m00 + 10;CvFont font = cvFont(0.7, 0.8);cvPutText(src, to_string(white).c_str(), p, &font, cvScalar(0, 0, 0));}cout << white << endl;cvReleaseMemStorage(&storage); //以下部分是计算黑棋cvThreshold(gray, bw, THRESH2, 255, CV_THRESH_BINARY_INV);elem = cvCreateStructuringElementEx(9, 9, 4, 4, CV_SHAPE_ELLIPSE);//cvDilate(bw, bw, elem, 1);cvErode(bw, bw, elem, 1);cvReleaseStructuringElement(&elem);/*showImg(bw, "二值化1");*/storage = cvCreateMemStorage(0);CvSeq* cont1 = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage);cvFindContours(bw, storage, &cont1, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0, 0));int black = 0;for (; cont1; cont1 = cont1->h_next){int count = cont1->total;if (count < 10 || count > 100)continue;black++;CvMoments mom;cvMoments(cont1, &mom, true);CvPoint p;p.x = mom.m10 / mom.m00 - 10;p.y = mom.m01 / mom.m00;CvFont font = cvFont(0.7, 0.8);cvPutText(src, to_string(black).c_str(), p, &font, cvScalar(255, 255, 255));}cvReleaseMemStorage(&storage);cout << black << endl;CvFont font = cvFont(1, 0.5);string text = "Black chessman: " + to_string(black);cvPutText(src, text.c_str(), cvPoint(10, 20), &font, cvScalar(255, 0, 0));text = "White chessman: " + to_string(white);cvPutText(src, text.c_str(), cvPoint(10, 45), &font, cvScalar(0, 0, 255));cvSaveImage("E:/result.jpg", src);/*showImg(src, "对比");*/        cvReleaseImage(&src);cvReleaseImage(&gray);cvReleaseImage(&bw);cvWaitKey(0);return 0;
}
代码写得匆忙,可能很粗糙,请匆见怪!如果自己想实验,像阈值这些地方,可以自己想办法确定,不一定取上面例子中的阈值。还有腐蚀,也不一定是cvCreateStructuringElementEx(9, 9, 4, 4, CV_SHAPE_ELLIPSE); 同样可以根据不同情况,做相应调整。

用OpenCV编程计算围棋棋盘黑白子总数相关推荐

  1. 有红、黄、绿三种颜色的球,其中红球 3 个, 黄球 3 个,绿球 6 个。先将这 12 个球混合放在一个盒子中,从中任意摸出 8 个球,编程计算摸出球的各种颜色搭配。1. 输出情况总数;2.输出摸取情

    内容1:有红.黄.绿三种颜色的球,其中红球 3 个, 黄球 3 个,绿球 6 个.先将这 12 个球混合放在一个盒子中,从中任意摸出 8 个球,编程计算摸出球的各种颜色搭配.1. 输出情况总数;2.输 ...

  2. MATLAB编程计算出电动车动力电池串联数、并联数、单体电池总数

    MATLAB编程计算出该车动力电池串联数.并联数.单体电池总数 一辆载高速上匀速行驶的汽车,车速为200km/h,传动系统效率0.85,空气阻力系数Cd=0.3:车辆迎风面积为1.2m^2,整车质量m ...

  3. 围棋棋盘怎么编程python_python3 turtle 画围棋棋盘

    python3 环境 利用turtle模块画出 围棋棋盘 #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Hiuhung Wan impor ...

  4. python 用turtle库画围棋棋盘和正、余弦函数图形

    一.如何画围棋棋盘. 围棋棋盘共有19纵19横.其中,位于(0,0)的星位叫天元,其余8个星位坐标分别是:(-6,6),(0,6),(6,6),(-6,0),(6,0),(-6,-6),(0,-6), ...

  5. 【Python】有红、黄、绿三种颜色的球,编程计算摸出球的各种颜色搭配

    Python三色球问题 题目 代码 结果 题目 有红.黄.绿三种颜色的球,其中红球 3 个, 黄球 3 个,绿 球 6 个.先将这 12 个球混合放在一个盒子中,从中任意摸 出 8 个球,编程计算摸出 ...

  6. python一对小兔子一年后长大成大兔子;一对大兔子每半年生一对小兔子。大兔子的繁殖期为4年,兔子的寿命是6年。假定第一年年初投放了一对小兔子,试编程计算,第n年末(不考虑死亡情况)总共会有多少对兔子

    题目为:一对小兔子一年后长大成大兔子:一对大兔子每半年生一对小兔子.大兔子的繁殖期为4年,兔子的寿命是6年.假定第一年年初投放了一对小兔子,试编程计算,第n年末(不考虑死亡情况)总共会有多少对兔子.n ...

  7. opencv学习---计算图像的水平积分投影和垂直积分投影

    opencv学习---计算图像的水平积分投影和垂直积分投影 标签: opencv水平积分投影垂直积分投影 2016-12-07 18:48 1806人阅读 评论(1) 收藏 举报 分类: opencv ...

  8. 基于python及图像识别的围棋棋盘棋子识别4——源码及使用说明

    最近在做一个围棋棋盘棋子识别项目,这是该项目第四篇,系列文章如下: 1.基于python及图像识别的围棋棋盘棋子识别1--定位棋盘位置 2.基于python及图像识别的围棋棋盘棋子识别2--定位棋子位 ...

  9. 智能电子围棋棋盘大盘点

    所谓电子棋盘,抑或智能棋盘,是安装了棋子检测传感器,能识别对弈双方的落子,进而能实现记录棋谱.人机/联网对战等功能的棋盘.智能电子棋盘相对于传统棋盘,增加了智能的对战和复盘.打谱学习等功能,又相比较电 ...

最新文章

  1. 如何用python和pip安装在txt文件中配置好版本的库包
  2. ZOJ3531: [SDOI2014] 旅行
  3. CTFshow 文件包含 web117
  4. (赞助5本)谷歌官方推荐的 TensorFlow 2 “豹书”来了!
  5. Python协同过滤推荐算法(Collaborative Filtering)2.相似度的计算,相似度计算方法
  6. smartqq java撤回_基于nodejs的http模块通过smartqq实现自动收发qq消息的程序
  7. 然爸读书笔记(2014-5)----团队正能量
  8. Linux拓展通配符的使用
  9. sBRDF空间双向反射分布函数完全解析
  10. 2018年全国多校算法寒假训练营练习比赛(第一场)C. 六子冲(模拟)
  11. vue获取麦克风_HTML5操作麦克风获取音频数据(WAV)的一些基础技能
  12. Apple Pay编程指南
  13. PageHelper.startPage()使用问题:,以及利用PageInfo和Page手动分页
  14. [每日一题]10、一道关于九宫格的面试题
  15. 打开SharePoint时遇到“Server error: http://go.microsoft.com/fwlink?LinkID=96177”
  16. 使用 Travis-CI 部署 HEXO 博客
  17. 笔记本电脑如何蹭WiFi
  18. python绘画海贼王_Python入门之生成海贼王云图
  19. php 批量删除注释,PHP-php做一个程序高效去除注释的方法
  20. c++,全局函数做友名

热门文章

  1. 【第03题】给定 a 和 b ,交换它们的值并输出 | 四种解法
  2. VS019下的VSColorOutput插件,可以改变vs输出窗口的颜色
  3. [manjaro] unzip-icon解决解压zip文件乱码
  4. 【操作系统】:操作系统概述
  5. 后端获取不到前端传来的参数值
  6. 码云最新出炉:亿万流量网站高性能框架设计方案,优化度达到100%
  7. vfp spt连接mysql_VFP中用SPT访问SQL Server数据库_mysql
  8. 简单解决easyocr识别文字结果上下窜行问题
  9. 体绘制(Volume Rendering)概述
  10. 姓雷取名:雷姓好听到爆的女孩名字