import os import sys import cv2 as cv import numpy as np import scipy.cluster import scipy.ndimage from annotations import DataFile,computeBoundingBox from hough import show def kmeans(img): arr=np.reshape(img,(-1,3)).astype(np.float) colors=np.array([[0,0,0],[255,255,255],[193,165,116]],np.float) print(colors) (centers,distortion)=scipy.cluster.vq.kmeans(arr,colors) print("k-means centers:",centers) return centers def quantize(img,centers): origShape=img.shape data=np.reshape(img,(-1,3)) (keys,dists)=scipy.cluster.vq.vq(data,centers) pixels=np.array([centers[k] for k in keys],dtype=np.uint8).reshape(origShape) return pixels def filterContours(contours,bwImg,stoneDims): contourImg=cv.cvtColor(bwImg,cv.COLOR_GRAY2BGR) res=[] for (i,c) in enumerate(contours): keep=True print(i) moments=cv.moments(c) center=(moments["m10"]/(moments["m00"] or 1), moments["m01"]/(moments["m00"] or 1)) print("center:", center) area=cv.contourArea(c) print("area:",area) (x,y,w,h)=cv.boundingRect(c) print("bounding box:",(x,y,w,h)) if w>stoneDims[0] or h>stoneDims[1]*1.3 or w<2 or h<2: cv.drawMarker(contourImg,tuple(map(int,center)),(0,0,255),cv.MARKER_TILTED_CROSS,12) keep=False coverage1=area/(w*h or 1) print("coverage1:",coverage1) hull=cv.convexHull(c) coverage2=area/(cv.contourArea(hull) or 1) print("coverage2:",coverage2) if coverage2<0.8: cv.drawMarker(contourImg,tuple(map(int,center)),(0,127,255),cv.MARKER_DIAMOND,12) keep=False print() if keep: res.append(c) cv.drawMarker(contourImg,tuple(map(int,center)),(255,0,0),cv.MARKER_CROSS) show(contourImg) return res if __name__=="__main__": filepath=sys.argv[1] annotations=DataFile(sys.argv[2]) filename=os.path.basename(filepath) (x1,y1,x2,y2)=computeBoundingBox(annotations[filename][0]) (w,h)=(x2-x1,y2-y1) img=cv.imread(filepath) (x3,x4,y3,y4)=(x1+w//4,x1+3*w//4,y1+h//4,y1+3*h//4) print("x3,x4,y3,y4:",x3,x4,y3,y4) rect=img[y3:y4,x3:x4,:] centers=kmeans(rect) print("x1,x2,y1,y2:",(x1,x2,y1,y2)) img[y1:y2,x1:x2,:]=quantize(img[y1:y2,x1:x2,:],centers) print("image quantized") rect=img[y1:y2,x1:x2] unit=np.array([1,1,1],dtype=np.uint8) maskB=cv.inRange(rect,centers[0]-unit,centers[0]+unit) maskB=cv.dilate(maskB,np.ones((3,3),np.uint8),iterations=1) maskB=cv.erode(maskB,np.ones((3,3),np.uint8),iterations=3) maskW=cv.inRange(rect,centers[1]-unit,centers[1]+unit) maskW=cv.erode(maskW,np.ones((3,3),np.uint8),iterations=2) show(img,filename) show(maskB,filename) show(maskW,filename) stones=cv.bitwise_or(maskB,maskW) show(stones) stoneDims=(w/19,h/19) print("stone dims:",tuple(x/2 for x in stoneDims),"-",stoneDims) (contours,hierarchy)=cv.findContours(stones,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE) filterContours(contours,stones,stoneDims)