diff --git a/exp/histogram.py b/exp/stone_detect.py rename from exp/histogram.py rename to exp/stone_detect.py --- a/exp/histogram.py +++ b/exp/stone_detect.py @@ -1,56 +1,16 @@ import os import sys -import random import cv2 as cv import numpy as np import scipy.cluster import scipy.ndimage -from matplotlib import pyplot as plt -import PIL.Image -from PIL.ImageDraw import ImageDraw from annotations import DataFile,computeBoundingBox -from hough import show,houghLines +from hough import show -def createHistogram(img): - # Convert BGR to HSV - hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV) - # H in range(0,180) - # S in range(0,256) - # V in range(0,256) - planes=cv.split(hsv) - hhist=cv.calcHist(planes,[0],None,[256],(0,180),accumulate=False) - shist=cv.calcHist(planes,[1],None,[256],(0,256),accumulate=False) - vhist=cv.calcHist(planes,[2],None,[256],(0,256),accumulate=False) - - width=512 - height=400 - binSize=width//256 - - histImage = np.zeros((height, width, 3), dtype=np.uint8) - cv.normalize(hhist, hhist, alpha=0, beta=height, norm_type=cv.NORM_MINMAX) - cv.normalize(shist, shist, alpha=0, beta=height, norm_type=cv.NORM_MINMAX) - cv.normalize(vhist, vhist, alpha=0, beta=height, norm_type=cv.NORM_MINMAX) - - for i in range(1, 256): - cv.line(histImage, ( binSize*(i-1), height - int(round(hhist[i-1][0])) ), - ( binSize*(i), height - int(round(hhist[i][0])) ), - ( 255, 0, 0), thickness=2) - cv.line(histImage, ( binSize*(i-1), height - int(round(shist[i-1][0])) ), - ( binSize*(i), height - int(round(shist[i][0])) ), - ( 0, 255, 0), thickness=2) - cv.line(histImage, ( binSize*(i-1), height - int(round(vhist[i-1][0])) ), - ( binSize*(i), height - int(round(vhist[i][0])) ), - ( 0, 0, 255), thickness=2) - - cv.imshow('Source image', img) - cv.imshow('calcHist Demo', histImage) - cv.waitKey() - - -def quantize(img): +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) @@ -59,100 +19,44 @@ def quantize(img): return centers -def computeClosest(x,centers): - res=centers[0] - d=np.linalg.norm(res-x) - for c in centers: - d_=np.linalg.norm(c-x) - if d_127 and arr[2,2]==m else 0 - -def ellipse(a,b): - img=PIL.Image.new("1",(a,b)) - d=ImageDraw(img) - d.ellipse((1,1,a-1,b-1),fill=1) - img.save("/tmp/ellipse.png") - return np.array(img,dtype=np.uint8) - -def detectStones(img): - (bh,bw)=img.shape - sw=bw//19 - sh=bh//19 - print(img.shape,(sw,sh)) - ell=ellipse(sw,sh)*255 - # print(ell) - hitMap=np.zeros_like(img,dtype=np.uint8) - for i in range(sw,bw): - for j in range(sh,bh): - region=stones[j-sh:j, i-sw:i] - hitMap[j,i]=255*score(region,ell) - show(hitMap) - return hitMap - -def detectGrid(img): - (bh,bw)=img.shape - - gridMap=np.zeros_like(img,dtype=np.uint8) - for i in range(5,bw): - for j in range(5,bh): - region=img[j-5:j, i-5:i] - gridMap[j,i]=255*maxOp55(region) - show(gridMap) - -def locateStone(img): - (bh,bw)=img.shape - sw=bw//19 - sh=bh//19 - print(img.shape,(sw,sh)) - ell=ellipse(sw,sh)*255 - # print(ell) - - y=random.randrange(sh,bh) - x=random.randrange(sw,bw) - region=stones[y-sh:y, x-sw:x] - sc=score(region,ell) - print(sc) - show(region) - return sc - -def locateLocalMaximum(img): - (bh,bw)=img.shape - x=random.randrange(0,bw) - y=random.randrange(0,bh) - val=img[y,x] - img_=cv.cvtColor(img,cv.COLOR_GRAY2BGR) - while True: - for (dx,dy) in [(0,1),(1,0),(0,-1),(-1,0),(1,1),(-1,1),(1,-1),(-1,-1)]: - x_=x+dx - y_=y+dy - val_=img[y_,x_] if 0<=x_val: - x=x_ - y=y_ - val=val_ - img_.itemset((y,x,0),255) - continue - break - print(x,y,val) - img_.itemset((y,x,2),255) - show(img_) - return (x,y,val) +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__": @@ -165,64 +69,27 @@ if __name__=="__main__": (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=quantize(rect) + centers=kmeans(rect) print("x1,x2,y1,y2:",(x1,x2,y1,y2)) - data=np.reshape(img[y1:y2,x1:x2,:],(-1,3)) - print("data.shape:",data.shape) - (keys,dists)=scipy.cluster.vq.vq(data,centers) - print("keys.shape:",keys.shape) - pixels=np.array([centers[k] for k in keys],dtype=np.uint8).reshape((y2-y1,x2-x1,3)) - img[y1:y2,x1:x2,:]=pixels + img[y1:y2,x1:x2,:]=quantize(img[y1:y2,x1:x2,:],centers) print("image quantized") rect=img[y1:y2,x1:x2] - maskB=cv.inRange(rect,np.array([0,0,0]),np.array([80,80,80])) - maskB=cv.erode(maskB,np.ones((3,3),np.uint8),iterations=2) - maskW=cv.inRange(rect,np.array([160,160,160]),np.array([256,256,256])) + 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) - # houghLines(stones) 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) - contourImg=cv.drawContours(cv.cvtColor(stones,cv.COLOR_GRAY2BGR), contours, -1, (0,255,0), 1) - for (i,c) in enumerate(contours): - print(i) - moments=cv.moments(c) - center=(moments["m10"]/(moments["m00"] or 1), moments["m01"]/(moments["m00"] or 1)) - print("center:", center) - cv.circle(contourImg,tuple(map(int,center)),3,(255,255,0)) - area=cv.contourArea(c) - print("area:",area) - (x,y,w,h)=cv.boundingRect(c) - print("bounding box:",(x,y,w,h)) - print("coverage1:",area/(w*h or 1)) - hull=cv.convexHull(c) - print("coverage2:",area/(cv.contourArea(hull) or 1)) - print() - show(contourImg) - - # for i in range(10): - # locateStone(stones) - # distMap=cv.distanceTransform(stones,cv.DIST_L2,5) - # print("dist map:") - # show(distMap) - # print("hit map:") - # hitMap=detectStones(stones) - # for i in range(10): - # locateLocalMaximum(hitMap) -# dlib.find_peaks - -# ministones=cv.resize(stones,None,fx=0.25,fy=0.25,interpolation=cv.INTER_AREA) -# dft = cv.dft(np.float32(ministones),flags = cv.DFT_COMPLEX_OUTPUT) -# dft_shift = np.fft.fftshift(dft) -# magnitude_spectrum = 20*np.log(cv.magnitude(dft_shift[:,:,0],dft_shift[:,:,1])) -# plt.subplot(121),plt.imshow(stones, cmap = 'gray') -# plt.title('Input Image'), plt.xticks([]), plt.yticks([]) -# plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray') -# plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([]) -# plt.show() + filterContours(contours,stones,stoneDims)