002 棋盘切成小片+判断是否有圆+颜色提取+截取圆形
棋盘切成小片:在之前已经是规范的图形了,所以这里切成小片也是规范的。
判断是否有圆:有圆的就是有棋子的位置,否则就是空位置。
颜色提取:棋子分红色和黑色的,但因为光影的影响,有一些经验数值,结合整个棋盘的颜色平均值,分类两种颜色的棋子。
截取圆形:根据之前判断是否有圆的函数(某个地方似乎我有理解错误,总是出现[0,0]坐标,打了个小补丁),将棋子的圆形规范的截取了出来。
# -*- coding: utf-8 -*-
import cv2
import numpy as np
from PIL import Image
import sys
import os, math
import argparse
import matplotlib.pyplot as plt # plt 用于显示图片
import matplotlib.image as mpimg # mpimg 用于读取图片
def cut_image(image):
print("把图片切成小块")
width,height=image.size
#print(width,height)
item_width=int(width/11)
#print(item_width)
item_height=int(height/12)
#print(item_height)
box_list=[]
count=0
for j in range(12):
for i in range(11):
count+=1
#box=(i*item_width,j*item_height,(i+1)*item_width,(j+1)*item_height)
box=((i*item_width)-20,(j*item_height)-20,((i+1)*item_width)+20,((j+1)*item_height)+20)
# 适当多切一点 以免摆放不规则的出了画面 上下左右多20个像素 方便把圆找出来
#print(count)
box_list.append(box)
#print(count)
image_list=[image.crop(box) for box in box_list]
return image_list
def get_color_c():
#获取这张图片的颜色
img_path = 'c.png'
image = Image.open(img_path)
# 要提取的主要颜色数量
num_colors = 1
small_image = image.resize((80, 80))
result = small_image.convert('P', palette=Image.ADAPTIVE, colors=num_colors)
result = result.convert('RGB')
# result.show() # 显示图像
main_colors = result.getcolors(80*80)
print(main_colors)
return main_colors[0][1][0] #只返回红色
def save_images(image_list):
print("保存切出的小块")
index=1
RGB_list=[]
theR = get_color_c()+37 #在c.png的R值基础上加上37 感觉应该可以区分出黑色和红色
for images in image_list:
print(index)
#images_yuan = img_to_circle(images) #截取中间的圆形
#images_zhong = images.crop((35,35,105,105))
images_zhong = images.crop((45,45,95,95))
theRGB = color_analy(images_zhong) #实际上测的是中间部分的RGB
print(theRGB)
RGBarr = theRGB[0][1]
RGB_list.append(RGBarr)
togall = theRGB[0][1][0]+theRGB[0][1][1]+theRGB[0][1][2]
#images.save(r'./c/'+str(index)+'.png')
images.save(r'./c/tmp.png')
had_circle_r, circles_x = had_circle('./c/tmp.png')
# d目录下 生成带圈圈标记的图片 debug用 以下可以不要
if had_circle_r != "nocircle":
img = mpimg.imread('./c/tmp.png')
for i in circles_x[:]:
cv2.circle(img,(i[0],i[1]),i[2],(255,0,0),5)
cv2.circle(img,(i[0],i[1]),2,(255,0,255),10)
cv2.rectangle(img,(i[0]-i[2],i[1]+i[2]),(i[0]+i[2],i[1]-i[2]),(255,255,0),5)
print("圆心坐标",i[0],i[1])
pointx = i[0]
pointy = i[1]
pointl = i[2] #半径
plt.subplot(1,1,1)
plt.axis('off') # 不显示坐标轴
plt.imshow(img)
fig = plt.gcf()
#plt.savefig('./d/'+str(index)+'.png')
#plt.show()
if i[0]==0 and i[1]==0:
# 【0,0】坐标补丁,某一些明明单独能识别出来,就是批量识别的时候出不来
img = cv2.imread('./c/tmp.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
circles1 = cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1.2, 200)
circles = circles1[0,:,:]
circles = np.uint16(np.around(circles))
for x in circles[:]:
cv2.circle(img,(x[0],x[1]),x[2],(255,0,0),5)
cv2.circle(img,(x[0],x[1]),2,(255,0,255),10)
cv2.rectangle(img,(x[0]-x[2],x[1]+x[2]),(x[0]+x[2],x[1]-x[2]),(255,255,0),5)
print("重新识别的圆心坐标",x[0],x[1])
pointx = x[0]
pointy = x[1]
pointl = x[2] #半径
plt.subplot(1,1,1)
plt.axis('off') # 不显示坐标轴
plt.imshow(img)
fig = plt.gcf()
#plt.savefig('./d/'+str(index)+'.png')
#plt.show()
plt.savefig('./d/'+str(index)+'_'+str(pointx)+'_'+str(pointy)+'_'+str(pointl)+'.png')
# d文件夹里保存框圈出来的棋子
# 此时已经有 圆心坐标和半径了
# d目录下 生成带圈圈标记的图片 debug用 以上可以不要
if had_circle_r == "nocircle":
#images.save(r'./c/'+str(index)+'_'+str(index)+'nocircle'+'.png')
print("本位置没有棋子,不用输出保存了")
else:
#if togall < 514 and theRGB[0][1][0] < 202 and theRGB[0][1][1] < 160 and theRGB[0][1][2] < 157 :
if theRGB[0][1][0] < theR and theRGB[0][1][0] > 37:
#只需要一个红色的值作为判断就够了 有一些漏网之鱼R值特别小 不知道为啥会被识别为一个圈
#images_zhong.save(r'./c/'+str(index)+'_black_'+str(theRGB[0][1][0])+'.png')
#images.save(r'./c/'+str(index)+'_black_'+str(theRGB[0][1][0])+'.png')
images = img_to_circle(images,pointx,pointy,pointl)
images.save(r'./c/'+str(index)+'.png')
#images_zhong.save(r'./c/black_'+str(index)+'_'+str(togall)+'_'+str(theRGB[0][1][0])+'_'+str(theRGB[0][1][1])+'_'+str(theRGB[0][1][2])+'.jpg')
elif theRGB[0][1][0] >= theR :
#images_zhong.save(r'./c/'+str(index)+'_red_'+str(theRGB[0][1][0])+'.png')
images = img_to_circle(images,pointx,pointy,pointl)
images.save(r'./c/'+str(index)+'.png')
#images_zhong.save(r'./c/red_'+str(index)+'_'+str(togall)+'_'+str(theRGB[0][1][0])+'_'+str(theRGB[0][1][1])+'_'+str(theRGB[0][1][2])+'.jpg')
else:
#漏网之鱼 空白无圈的
#images.save(r'./c/'+str(index)+'_nocircle'+'.png')
print("漏网之鱼?")
index+=1
return RGB_list
# 这个是机械的截取圆形的函数
def img_to_circle0(ima):
#def img_to_circle():
#ima = Image.open("b/86_69_63.jpg").convert("RGBA")
ima = ima.convert("RGBA")
size = ima.size
# 因为是要圆形,所以需要正方形的图片
r2 = min(size[0], size[1])
if size[0] != size[1]:
ima = ima.resize((r2, r2), Image.ANTIALIAS)
imb = Image.new('RGBA', (r2, r2),(255,255,255,0))
pima = ima.load()
pimb = imb.load()
r = float(r2/2) #圆心横坐标
for i in range(r2):
for j in range(r2):
lx = abs(i-r+0.5) #到圆心距离的横坐标
ly = abs(j-r+0.5) #到圆心距离的纵坐标
l = pow(lx,2) + pow(ly,2)
if l <= pow(r, 2):
pimb[i,j] = pima[i,j]
return imb
#imb.save("test_circle.png")
# 这个其实是根据圆心坐标和半径先截取出一个矩形,然后再嵌套规矩的圆形切取函数,在切出棋子的圆形
def img_to_circle(ima,px,py,pl):
x0 = px-pl
y0 = py-pl
x1 = px+pl
y1 = py+pl
#ima = ima[y0:y1, x0:x1] #[y0:y1, x0:x1]
ima = ima.crop((x0, y0, x1, y1)) # (left, upper, right, lower)
img_a_cycle = img_to_circle0(ima)
return img_a_cycle
def had_circle(imagepath):
# 判断切出的小画面当中 是否有圆形存在
image = cv2.imread(imagepath)
#output = image.copy()
image = image[0:125, 0:125] #[y0:y1, x0:x1]
# 130*130似乎有点太大范围了 容易把空白识别为有棋子 所以改略小一点
#image = cv2.resize(image, (300,300))
# 改变大小并不能改善识别和打圈的状况
# 将其转换为灰度图片
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 25, 10)
# 应用hough变换进行圆检测
#circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2, 200)
circles0 = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2, 200)
if circles0 is None: #为空值的情况是没有圆 有一些光影会造成把没有棋子的地方误认为有棋子 这种到后面再去解决 设置一个模式都不匹配的 就认定为没有棋子
print("无圆") # 就是 空白无棋子的地方
toreturn = "nocircle"
circles = "no"
else:
toreturn = circles0
print(circles0)
circles = circles0[0,:,:]
circles = np.uint16(np.around(circles))
return toreturn,circles # circles 是为了生成带圈圈标记的图片debug用 若拖慢了速度 可以不要
def color_analy(theimage):
print("分析小块图片的颜色")
# 计算一张图片的主要颜色的RGB
#img_path = 'b/12.jpg'
#theimage = Image.open(img_path)
# 要提取的主要颜色数量
num_colors = 1 #个数可以改
# small_image = image.resize((80, 80))
# result = small_image.convert('P', palette=Image.ADAPTIVE, colors=num_colors) # image with 5 dominating colors
result = theimage.convert('P', palette=Image.ADAPTIVE, colors=num_colors)
result = result.convert('RGB')
# result.show() # 显示图像
# main_colors = result.getcolors(80*80)
main_colors = result.getcolors(100*100)
return main_colors
'''
# 显示提取的主要颜色
for count, col in main_colors:
if count < 40:
continue
a = np.zeros((224,224,3))
a = a + np.array(col)
# print(a)
cv2.imshow('a',a.astype(np.uint8)[:,:,::-1])
cv2.waitKey()
'''
image=Image.open(r'c.png')
#切分图像
image_list=cut_image(image)
#保存切分的图像
# 保存之后会做颜色分析
point = save_images(image_list)
#分析颜色 是黑棋 还是红棋 还是空白(棋盘换成白色)


1万+

被折叠的 条评论
为什么被折叠?



