002 棋盘切成小片+判断是否有圆+颜色提取+截取圆形

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)
#分析颜色 是黑棋 还是红棋 还是空白(棋盘换成白色)


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值