├── CircleDetection ├── c.png ├── circle.py └── img │ ├── OneCircle.png │ └── OneCircle_output.png ├── EdgeDetection ├── EdgeDetection.py ├── EdgeDetection.pyc ├── __init__.py ├── img │ ├── coins.jpg │ └── figures.png └── main.py ├── EllipseDetection ├── EllipseDetection.py └── img │ ├── Tangents.png │ ├── Voting.png │ ├── VotingLine.png │ └── ellipse.png ├── HoleDetection ├── img │ ├── bulletHoles.jpg │ ├── bulletHoles2.jpg │ ├── bulletHoles2_output.png │ ├── bulletHoles_output.png │ ├── holeSheet.jpg │ └── holeSheet_output.png └── main.py ├── LineDetection ├── img │ ├── chess.png │ ├── chess_output.png │ ├── pedestrianCrossing.jpg │ ├── pedestrianCrossing_output.png │ ├── table_1.jpg │ ├── table_1_output.png │ ├── trainTracks.jpg │ └── trainTracks_output.png └── main.py ├── MeasurementSystem-Project.pdf ├── MeasurementSystem ├── Final_Presentation.pdf ├── GUI.py ├── MeasurementSystem.py ├── README.md ├── Report.pdf └── Tests │ ├── INPUT │ ├── 0.jpg │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ └── 4.jpg │ ├── OUTPUT │ ├── 0.png │ ├── 1.png │ ├── 2.png │ ├── 2pointsGiven.png │ ├── 3.png │ └── 4.png │ └── video.mp4 ├── README.md ├── ShapeDetection ├── ShapeDetection.py ├── __init__.py ├── __init__.pyc ├── img_testing │ ├── centerOfMass.png │ ├── coins_original.jpg │ ├── findingForms.png │ ├── other_figures.png │ └── other_figures_modified.png └── main.py └── findingThings ├── main.py └── pictures ├── circle.jpg └── circle2.jpg /CircleDetection/c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/CircleDetection/c.png -------------------------------------------------------------------------------- /CircleDetection/circle.py: -------------------------------------------------------------------------------- 1 | from random import randint, random 2 | from math import sqrt, ceil, floor, fabs, atan2, cos, sin 3 | import numpy as np 4 | import cv2 5 | from ShapeDetection import ShapeDetection as sd 6 | 7 | def circleEquation(x,xc,y,yc,r): 8 | c = (x-xc)**2 + (y-yc)**2 9 | r2 = r**2 10 | # r2-200 <= c <= r2 11 | return c <= r2 and c >= (r2-200) 12 | 13 | def applyDGMasks(img,heigh,width,mask,border): 14 | print "applying DG mask" 15 | Gx = [] 16 | Gy = [] 17 | for y in range(1,height-1,1): 18 | 19 | for x in range(1,width-1,1): 20 | if [y,x] in border: 21 | pixelGradients = [] 22 | 23 | # used to get the equivalent position in the mask 24 | indexer = [-y+1,-x+1] 25 | 26 | for i in range(len(mask)): 27 | gradient = 0 28 | # used for a neighborhood 3x3... I need to improve it 29 | for r in range(y-1, y+2): 30 | for c in range(x-1,x+2): 31 | #convolution matrix * each pixel 32 | gradient += img[r,c]*mask[i][r+indexer[0]][c+indexer[1]] 33 | 34 | #the gradient of the mask applied is stored 35 | pixelGradients.append(gradient) 36 | 37 | Gx.append(pixelGradients[0]) 38 | Gy.append(pixelGradients[1]) 39 | 40 | return Gx,Gy 41 | 42 | 43 | 44 | 45 | mask = [ 46 | [ [-1,0,1], [-2,0,2], [-1,0,1] ], 47 | [ [1,2,1], [0,0,0], [-1,-2,-1] ] 48 | ] 49 | 50 | #starting 51 | shapeDetector = sd.ShapeDetection() 52 | shapeDetector.test.path = "CircleDetection/c.png" 53 | shapeDetector.test.detectBorders() 54 | #figures = shapeDetector.detectFigures() 55 | #shapeDetector.drawBoundingBox(shapeDetector.test.border) 56 | height = shapeDetector.test.height 57 | width = shapeDetector.test.width 58 | 59 | for pixel in shapeDetector.test.border: 60 | 61 | shapeDetector.test.originalImg[pixel[0],pixel[1]] = [0,0,255] 62 | 63 | 64 | i = shapeDetector.test.border 65 | i.sort() 66 | n_elem = len(i) 67 | print "i[0][0]: ",i[0][0] 68 | y_min = i[0][0] 69 | y_max = i[n_elem-1][0] 70 | x_min = i[n_elem-1][1] 71 | x_max = 0 72 | 73 | sum_x = 0 74 | sum_y = 0 75 | 76 | for e in i: 77 | sum_x += e[1] 78 | sum_y += e[0] 79 | 80 | if e[1] > x_max: 81 | x_max = e[1] 82 | if e[1] < x_min: 83 | x_min = e[1] 84 | 85 | color = [0,255,0] 86 | 87 | for z in range(x_min,x_max+1): 88 | shapeDetector.test.originalImg[y_min,z] = color 89 | shapeDetector.test.originalImg[y_max,z] = color 90 | for z in range(y_min,y_max+1): 91 | shapeDetector.test.originalImg[z,x_min] = color 92 | shapeDetector.test.originalImg[z,x_max] = color 93 | 94 | centerOfMass = [sum_y/n_elem,sum_x/n_elem] 95 | radio = centerOfMass[1] - x_min 96 | 97 | for y in xrange(centerOfMass[0]-1,centerOfMass[0]+2,1): 98 | for x in xrange(centerOfMass[1]-1,centerOfMass[1]+2,1): 99 | shapeDetector.test.originalImg[y,x] = [0,0,255] 100 | 101 | Gx,Gy = applyDGMasks(shapeDetector.test.imgCopy,height,width,mask,shapeDetector.test.border) 102 | 103 | print "Gx: " 104 | print Gx 105 | print "Gy: " 106 | print Gy 107 | 108 | print "x_min: ",x_min," centerOfMass: ",centerOfMass," radio: ",radio 109 | 110 | votes = dict() 111 | 112 | for i in range(len(shapeDetector.test.border)): 113 | p = shapeDetector.test.border[i] 114 | shapeDetector.test.originalImg[p[0],p[1]] = [255,0,0] 115 | g = sqrt( Gx[i]**2 + Gy[i]**2 ) 116 | cosTheta = Gx[i] / g 117 | sinTheta = Gy[i] / g 118 | angle = atan2(Gy[i],Gx[i]) 119 | xc = int(round(p[1] - radio * cosTheta)) 120 | yc = int(round(p[0] - radio * sinTheta)) 121 | 122 | if xc >= 0 and xc < x_max and yc >= 0 and yc < y_max: 123 | shapeDetector.test.originalImg[yc,xc] = [0,255,255] 124 | vote = str(yc)+","+str(xc) 125 | if vote not in votes: 126 | votes[vote] = 1 127 | else: 128 | votes[vote] += 1 129 | bigger = "" 130 | for v in votes: 131 | if bigger == "": 132 | bigger = v 133 | elif votes[v] > votes[bigger]: 134 | bigger = v 135 | 136 | print bigger 137 | biggers = list() 138 | print "votes: ",votes 139 | print "votes >= 4: " 140 | 141 | for v in votes: 142 | if votes[v] >= 4: 143 | print "votes[",v,"] :",votes[v] 144 | biggers.append([int(v[0]+v[1]),int(v[3]+v[4])]) 145 | 146 | yc_d = int(bigger[0]+bigger[1]) 147 | xc_d = int(bigger[3]+bigger[4]) 148 | """ 149 | for y in xrange(yc_d-1,yc_d+2,1): 150 | for x in xrange(xc_d,xc_d+2,1): 151 | shapeDetector.test.originalImg[y,x] = [0,0,0] 152 | """ 153 | for p in biggers: 154 | shapeDetector.test.originalImg[p[0],p[1]] = [0,0,0] 155 | 156 | 157 | sum_x = 0 158 | sum_y = 0 159 | 160 | for e in biggers: 161 | sum_x += e[1] 162 | sum_y += e[0] 163 | 164 | lenght = len(biggers) 165 | center_c_d = [int(round(sum_y/lenght)),int(round(sum_x/lenght))] 166 | 167 | for y in xrange(center_c_d[0]-1,center_c_d[0]+2,1): 168 | for x in xrange(center_c_d[1],center_c_d[1]+2,1): 169 | shapeDetector.test.originalImg[y,x] = [0,0,0] 170 | 171 | print "borde 0: ",shapeDetector.test.border[0] 172 | """ 173 | for pixel in shapeDetector.test.border: 174 | shapeDetector.test.originalImg[pixel[0],pixel[1]] = [0,0,255] 175 | """ 176 | newRadio = center_c_d[1] - x_min 177 | for y in range(1,height-1,1): 178 | for x in range(1,width-1,1): 179 | if circleEquation(x,center_c_d[1],y,center_c_d[0],newRadio): 180 | shapeDetector.test.originalImg[y,x] = [0,140,255] 181 | 182 | 183 | cv2.imwrite("result_Circle.png",shapeDetector.test.originalImg) 184 | 185 | -------------------------------------------------------------------------------- /CircleDetection/img/OneCircle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/CircleDetection/img/OneCircle.png -------------------------------------------------------------------------------- /CircleDetection/img/OneCircle_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/CircleDetection/img/OneCircle_output.png -------------------------------------------------------------------------------- /EdgeDetection/EdgeDetection.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | from Tkinter import * 3 | from tkFileDialog import * 4 | import sys 5 | from numpy import * 6 | import math 7 | 8 | class EdgeDetection: 9 | 10 | def __init__(self): 11 | self.debug = 1 12 | 13 | if len(sys.argv) > 1: 14 | self.debug = int(sys.argv[1]) 15 | 16 | self.originalImg = None 17 | self.imgCopy = None 18 | self.height = None 19 | self.width = None 20 | self.path = None 21 | self.T = None 22 | 23 | #Robinson's "5-level" masks 24 | self.mask = [ 25 | [ [-1,0,1],[-2,0,2],[-1,0,1] ], #mask 1 26 | [ [0,1,2],[-1,0,1],[-2,-1,0] ], #mask 2 27 | [ [1,2,1],[0,0,0],[-1,-2,-1] ], #mask 3 28 | [ [2,1,0],[1,0,-1],[0,-1,-2] ], #mask 4 29 | [ [1,0,-1],[2,0,-2],[1,0,-1] ], #mask 5 30 | [ [0,-1,-2],[1,0,-1],[2,1,0] ], #mask 6 31 | [ [-1,-2,-1],[0,0,0],[1,2,1] ], #mask 7 32 | [ [-2,-1,0],[-1,0,1],[0,1,2] ] #mask 8 33 | ] 34 | 35 | #Sobel's mask for DG 36 | self.DGMasks = [ 37 | [ [-1,0,1], [-2,0,2], [-1,0,1] ], 38 | [ [1,2,1], [0,0,0], [-1,-2,-1] ] 39 | ] 40 | 41 | self.histogram = [] 42 | self.border = [] 43 | self.angles = [] 44 | self.borderInfo = [] 45 | 46 | def preProcessImg(self,imagePath): 47 | self.originalImg = cv2.imread(imagePath) 48 | self.img = cv2.cvtColor(self.originalImg,cv2.COLOR_RGB2GRAY) #convert to grayscale 49 | self.imgCopy = self.img 50 | self.height, self.width = self.img.shape 51 | if self.debug: 52 | print "-> height: ",self.height," width: ",self.width 53 | print "-> applying masks to each pixel" 54 | 55 | def applyMasks(self,pixel,img): 56 | 57 | pixelGradients = [] # used to store the gradients of each pixel 58 | indexer = [-pixel[0]+1,-pixel[1]+1] # used to get the equivalent position in the mask 59 | 60 | for i in range(len(self.mask)): 61 | gradient = 0 62 | for r in range(pixel[0]-1, pixel[0]+2): # used for a neighborhood 3x3... I need to improve it 63 | for c in range(pixel[1]-1,pixel[1]+2): 64 | gradient += img[r,c]*self.mask[i][r+indexer[0]][c+indexer[1]] #convolution matrix * each pixel 65 | 66 | pixelGradients.append(gradient) #the gradient of the mask applied is stored 67 | 68 | maxGradient = max(pixelGradients) #the gradient of the pixel is the maximum gradient obtained 69 | 70 | self.angles.append(self.setAngles(pixelGradients,maxGradient)) 71 | 72 | return maxGradient 73 | 74 | def applyDGMasks(self,pixel,img): 75 | pixelGradients = [] 76 | indexer = [-pixel[0]+1,-pixel[1]+1] # used to get the equivalent position in the mask 77 | 78 | for i in range(len(self.mask)): 79 | gradient = 0 80 | for r in range(pixel[0]-1, pixel[0]+2): # used for a neighborhood 3x3... I need to improve it 81 | for c in range(pixel[1]-1,pixel[1]+2): 82 | gradient += img[r,c]*self.mask[i][r+indexer[0]][c+indexer[1]] #convolution matrix * each pixel 83 | 84 | pixelGradients.append(gradient) #the gradient of the mask applied is stored 85 | 86 | maxGradient = abs(pixelGradients[0]) + abs(pixelGradients[1]) 87 | angle = math.atan2(pixelGradients[1],pixelGradients[0]) 88 | 89 | return maxGradient,angle 90 | 91 | def setAngles(self,pixelGradients,maxGradient): 92 | 93 | index = pixelGradients.index(maxGradient) + 1 94 | 95 | if index == 1 or index == 5: 96 | return 90 97 | elif index == 2 or index == 6: 98 | return 45 99 | elif index == 3 or index == 7: 100 | return 0 101 | else: 102 | return -45 103 | 104 | def getThreshold(self,histogram): 105 | #Basic global thresholding 106 | t_new = max(histogram)/2.0 #the threshold should be close to the center 107 | t_old = 0.0 108 | mean = [0,0] 109 | while abs(t_old-t_new) > 0.001: #the loop ends until the difference of the old threshold and the new one is minimum 110 | 111 | if self.debug: 112 | print "-> threshold: ",t_new 113 | 114 | mean = self.getAverages(t_new) #get the average of each side based on the current threshold 115 | t_old = t_new 116 | t_new = 0.5*(mean[0]+mean[1]) # get a new threshold by obtaining the average of the means 117 | 118 | self.T = t_new/2.5 119 | if self.debug: 120 | print "-> Final Threshold: ",self.T 121 | 122 | return self.T #We get a better border clearly defined by divinding the final Threshold into 2.5 123 | 124 | def getAverages(self,t): 125 | 126 | sum_upper = 0 127 | counter_upper = 0 128 | 129 | sum_down = 0 130 | counter_down = 0 131 | for e in self.histogram: 132 | if e > t: #sum all the gradients > threshold 133 | sum_upper += e 134 | counter_upper += 1 135 | else: #sum all the gradients < threshold 136 | sum_down += e 137 | counter_down += 1 138 | 139 | return [(sum_upper/counter_upper*1.0),(sum_down/counter_down*1.0)] #return means 140 | 141 | def getBorders(self, T): 142 | index_counter = 0 143 | for r in range(1,self.height-1,1): 144 | for c in range(1,self.width-1,1): 145 | #Change the color of the borders, borders in white, everything else in black 146 | if self.histogram[index_counter] > T: 147 | 148 | for i in range(r-1,r+2): #big border painting the neighborhood for each pixel border detected 149 | for j in range(c-1,c+2): 150 | self.border.append([i,j]) 151 | self.borderInfo.append([ [i,j],self.histogram[index_counter],self.angles[index_counter] ]) 152 | 153 | index_counter += 1 154 | 155 | def detectBorders(self): 156 | self.preProcessImg(self.path) 157 | for y in range(1,self.height-1,1): 158 | for x in range(1,self.width-1,1): 159 | gradient,angle = self.applyDGMasks([y,x],self.img) 160 | self.histogram.append(gradient) #Apply masks for each pixel and save the gradient in the histogram 161 | #self.borderInfo.append([ [y,x],gradient,angle ]) 162 | self.angles.append(angle) 163 | 164 | self.T = self.getThreshold(self.histogram) 165 | self.getBorders(self.T) 166 | -------------------------------------------------------------------------------- /EdgeDetection/EdgeDetection.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/EdgeDetection/EdgeDetection.pyc -------------------------------------------------------------------------------- /EdgeDetection/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/EdgeDetection/__init__.py -------------------------------------------------------------------------------- /EdgeDetection/img/coins.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/EdgeDetection/img/coins.jpg -------------------------------------------------------------------------------- /EdgeDetection/img/figures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/EdgeDetection/img/figures.png -------------------------------------------------------------------------------- /EdgeDetection/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import cv2 4 | from Tkinter import * 5 | from tkFileDialog import * 6 | import sys 7 | from numpy import * 8 | from EdgeDetection import EdgeDetection 9 | 10 | 11 | def paintBorder(test): 12 | for r in range(1,test.height-1,1): 13 | for c in range(1,test.width-1,1): 14 | if [r,c] in test.border: 15 | test.imgCopy[r,c] = 255 16 | else: 17 | test.imgCopy[r,c] = 0 18 | 19 | def processImage(): 20 | 21 | test = EdgeDetection() 22 | 23 | if test.debug: 24 | print "-> preprocessing the image" 25 | 26 | test.path = loadFile() 27 | 28 | if test.path == "": 29 | 30 | if test.debug: 31 | print "path: -" 32 | 33 | return 34 | 35 | if test.debug: 36 | print "-> path: ", test.path 37 | 38 | test.detectBorders() 39 | 40 | if test.debug: 41 | print "-> showing up borders" 42 | 43 | 44 | paintBorder(test) 45 | 46 | cv2.imwrite("img/result.png",test.imgCopy) #Write a new image 47 | 48 | print "-> image successfully saved at img/result.png" 49 | 50 | del test.histogram[:] # remove all the elements in the histogram 51 | 52 | print "-> You can choose another image ..." 53 | 54 | 55 | def loadFile(): 56 | fname = "" 57 | try: 58 | fname = askopenfilename(filetypes=(("All files", "*.*"), 59 | ("PNG", "*.png"))) 60 | 61 | except ValueError: 62 | print "Please select an image. Try again..." 63 | 64 | return fname 65 | 66 | 67 | master = Tk() 68 | 69 | f = Frame(master, height=300, width=300) 70 | f.pack_propagate(0) 71 | f.pack() 72 | 73 | b = Button(f, text="Load a picture", command = processImage) 74 | b.pack() 75 | 76 | master.title("Edge detection") 77 | mainloop() 78 | -------------------------------------------------------------------------------- /EllipseDetection/EllipseDetection.py: -------------------------------------------------------------------------------- 1 | from random import randint, random 2 | from math import sqrt, ceil, floor, fabs, atan2, cos, sin, pi 3 | import numpy as np 4 | import cv2 5 | from ShapeDetection import ShapeDetection as sd 6 | 7 | def getTangentEq(test): 8 | 9 | lenBorder = len(test.borderInfo) 10 | for i in range(0,lenBorder,20): 11 | point1,gradient1,angle1 = test.borderInfo[i] 12 | nextPoint = i+50 13 | if nextPoint >= lenBorder: 14 | nextPoint = lenBorder - i 15 | 16 | point2, gradient2, angle2 = test.borderInfo[nextPoint] 17 | 18 | eq1 = processTangent(point1,angle1,test) 19 | eq2 = processTangent(point2,angle2,test) 20 | print "eq1: ",eq1 21 | print "eq2: ",eq2 22 | y,x = getLinearEq(eq1,eq2,test) 23 | print "y,x: ",y,",",x 24 | 25 | if y != 0 and x != 0: 26 | 27 | if y > 0 and y < test.height and x > 0 and x < test.width: 28 | for r in range(y-1,y+2,1): 29 | for c in range(x-1,x+2,1): 30 | test.originalImg[r,c] = [0,0,255] 31 | 32 | drawLineBetweenPoints(point1,point2,test) 33 | middleP = [int(abs(point1[0]+point2[0])/2) , int(abs(point1[1] + point2[1])/2) ] 34 | print "middleP: ",middleP 35 | drawVotingLine(middleP,[y,x],test) 36 | cv2.imwrite("Tangents_ellipse.png",test.originalImg) 37 | 38 | return 39 | 40 | def processTangent(point,angle,test): 41 | 42 | angle = 3.1416/2-angle 43 | 44 | dx = cos(angle) 45 | dy = sin(angle) 46 | 47 | m = dx/dy 48 | 49 | secondPoint = [int(round(m*(100-point[1])+point[0])), 100] 50 | 51 | for c in xrange(test.width): 52 | y = int(round(m*(c-point[1])+point[0])) 53 | #print "y: ",y 54 | if y >= 0 and y < test.height: 55 | test.originalImg[y,c] = [0,255,0] 56 | 57 | #cv2.imwrite("Tangents_"+str(m)+".png",test.originalImg) 58 | 59 | eq = [m,point,secondPoint[0]] 60 | 61 | 62 | return eq 63 | 64 | def getLinearEq(eq1,eq2,test): 65 | 66 | y1, y2 = int(), int() 67 | 68 | for x in xrange(-test.width*6,test.width*6,1): 69 | y1 = int(round(eq1[0]*(x-eq1[1][1])+eq1[1][0])) 70 | y2 = int(round(eq2[0]*(x-eq2[1][1])+eq2[1][0])) 71 | if y1 == y2: 72 | print "y1 == y2 = ",y1 73 | return y1,x 74 | 75 | return 0,0 76 | 77 | def drawLineBetweenPoints(point1, point2,test): 78 | print "part1: ",(point2[0]-point1[0]) 79 | print "part2: ",(point2[1]-point1[1]) 80 | m = (point2[0]-point1[0])*1.0/(point2[1]-point1[1]) 81 | print "**m ",m 82 | 83 | b = min(point2[0],point1[0]) 84 | 85 | start = min(point1[1],point2[1]) 86 | finish = max(point1[1],point2[1]) 87 | 88 | print "p1, p2: ",point1," , ",point2 89 | 90 | for x in range(start,finish,1): 91 | y = int( round( m*(x - start) + b ) ) 92 | print "-.--> y: ",y," m: ",m," b: ",b 93 | if y > 0 and y < test.height: 94 | test.originalImg[y,x] = [255,0,0] 95 | 96 | #cv2.imwrite("Tangents_"+str(m)+".png",test.originalImg) 97 | 98 | return 99 | 100 | def drawVotingLine(point1, point2, test): 101 | 102 | #print "part1: ",(point2[0]-point1[0]) 103 | #print "part2: ",(point2[1]-point1[1]) 104 | part2 = (point2[1]-point1[1]) 105 | if part2 == 0: 106 | part2 = 1 107 | 108 | m = (point2[0]-point1[0])*1.0/part2 109 | #print "**m ",m 110 | 111 | b = min(point2[0],point1[0]) 112 | 113 | #start = point1[1] 114 | start = min(point1[1],point2[1]) 115 | 116 | finish = max(point1[1],point2[1]) 117 | 118 | print "p1, p2: ",point1," , ",point2 119 | 120 | for x in range(start,test.width,1): 121 | y = int( round( m*(x - start) + b ) ) 122 | print "votingL -> y: ",y," m: ",m," b: ",b 123 | 124 | 125 | if y > 0 and y < test.height: 126 | test.originalImg[y,x] = [0,0,0] 127 | if [y,x] not in test.border: 128 | test.originalImg[y,x] = [0,233,255] 129 | 130 | #cv2.imwrite("Tangents_"+str(m)+".png",test.originalImg) 131 | 132 | return 133 | 134 | def getAllTangents(test): 135 | 136 | for item in range(0,len(test.borderInfo)-1,1): 137 | point,gradient,angle = test.borderInfo[item]#test.borderInfo[300] 138 | 139 | print "Point1: ", point 140 | 141 | #test.originalImg[point[0],point[1]] = [255,0,0] #Paint point 1 142 | 143 | print "-> Gradient: ",gradient 144 | print "-> Angle: ",angle 145 | 146 | angle = 3.1416/2-angle 147 | 148 | print "angle: ", angle 149 | dx = cos(angle) 150 | dy = sin(angle) 151 | 152 | #m = dy/dx 153 | m = dx/dy 154 | print "dx,dy: ",dx,",",dy 155 | print "m: ",m 156 | 157 | 158 | #for r in xrange(test.height): 159 | for c in xrange(test.width): 160 | y = int(round(m*(c-point[1])+point[0])) 161 | #print "y: ",y 162 | if y >= 0 and y < test.height: 163 | test.originalImg[y,c] = [0,255,0] 164 | 165 | 166 | cv2.imwrite("Tangents_ellipse.png",test.originalImg) 167 | 168 | return 169 | 170 | def testPaintBorders(height,width,test): 171 | print "-> Painting borders" 172 | 173 | for l in test.borderInfo: 174 | 175 | coord = l[0] 176 | if coord[0] < height and coord[1] < width: 177 | test.originalImg[coord[0],coord[1]] = [0,0,255] 178 | 179 | 180 | cv2.imwrite("Borders_ellipse.png",test.originalImg) 181 | 182 | 183 | def main(): 184 | 185 | shapeDetector = sd.ShapeDetection() 186 | 187 | shapeDetector.test.path = "img/ellipse.png" 188 | 189 | #figures = shapeDetector.detectFigures() 190 | shapeDetector.test.detectBorders() 191 | 192 | width = shapeDetector.test.width 193 | height = shapeDetector.test.height 194 | 195 | #testPaintBorders(height,width, shapeDetector.test) 196 | #getAllTangents(shapeDetector.test) 197 | getTangentEq(shapeDetector.test) 198 | 199 | 200 | main() 201 | 202 | -------------------------------------------------------------------------------- /EllipseDetection/img/Tangents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/EllipseDetection/img/Tangents.png -------------------------------------------------------------------------------- /EllipseDetection/img/Voting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/EllipseDetection/img/Voting.png -------------------------------------------------------------------------------- /EllipseDetection/img/VotingLine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/EllipseDetection/img/VotingLine.png -------------------------------------------------------------------------------- /EllipseDetection/img/ellipse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/EllipseDetection/img/ellipse.png -------------------------------------------------------------------------------- /HoleDetection/img/bulletHoles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/HoleDetection/img/bulletHoles.jpg -------------------------------------------------------------------------------- /HoleDetection/img/bulletHoles2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/HoleDetection/img/bulletHoles2.jpg -------------------------------------------------------------------------------- /HoleDetection/img/bulletHoles2_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/HoleDetection/img/bulletHoles2_output.png -------------------------------------------------------------------------------- /HoleDetection/img/bulletHoles_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/HoleDetection/img/bulletHoles_output.png -------------------------------------------------------------------------------- /HoleDetection/img/holeSheet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/HoleDetection/img/holeSheet.jpg -------------------------------------------------------------------------------- /HoleDetection/img/holeSheet_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/HoleDetection/img/holeSheet_output.png -------------------------------------------------------------------------------- /HoleDetection/main.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | from EdgeDetection import EdgeDetection as ed 3 | from random import choice,randint 4 | 5 | def preProcessImg(imagePath): 6 | originalImg = cv2.imread(imagePath) 7 | img = cv2.cvtColor(originalImg,cv2.COLOR_RGB2GRAY) #convert to grayscale 8 | imgCopy = img 9 | height, width = img.shape 10 | 11 | return originalImg,img,imgCopy,height,width 12 | 13 | def getBorders(path): 14 | test = ed.EdgeDetection() 15 | 16 | test.path = path 17 | 18 | test.detectBorders() 19 | 20 | return paintBorder(test) 21 | 22 | def paintBorder(test): 23 | 24 | for r in range(1,test.height-1,1): 25 | for c in range(1,test.width-1,1): 26 | if [r,c] in test.border: 27 | test.imgCopy[r,c] = 0 28 | else: 29 | test.imgCopy[r,c] = 255 30 | return test.imgCopy 31 | 32 | def getHorizontalHistogram(height,width,imgCopy): 33 | hist = {} 34 | for c in range(1,width-1,1): 35 | sum_hist = 0 36 | for r in range(1,height-1,1): 37 | sum_hist += imgCopy[r,c] 38 | 39 | hist[c] = sum_hist 40 | 41 | return hist 42 | 43 | def getVerticalHistogram(height,width,imgCopy): 44 | hist = {} 45 | for r in range(1,height-1,1): 46 | sum_hist=0 47 | for c in range(1,width-1,1): 48 | sum_hist += imgCopy[r,c] 49 | hist[r] = sum_hist 50 | 51 | return hist 52 | 53 | def getPeaksByMean(histogram): 54 | peaks = {} 55 | sum_hist = 0 56 | 57 | for e in histogram: 58 | sum_hist += histogram[e] 59 | mean = sum_hist/len(histogram) 60 | 61 | for e in histogram: 62 | if histogram[e] < mean: 63 | peaks[e] = histogram[e] 64 | 65 | return peaks 66 | 67 | def getBackground(originalImg,height,width): 68 | 69 | colors = {} 70 | myBackground = {'color': 0, 'frequency':0} 71 | 72 | for r in range(height-1): 73 | for c in range(width-1): 74 | pixelColor = originalImg[r,c][0]+ (originalImg[r,c][1])+ originalImg[r,c][2] 75 | 76 | if pixelColor not in colors: 77 | 78 | colors[pixelColor] = 1 79 | 80 | if myBackground['color'] == 0: 81 | myBackground['color'] = pixelColor 82 | myBackground['frequency'] = 1 83 | else: 84 | colors[pixelColor] += 1 85 | 86 | if colors[pixelColor] > myBackground['frequency']: 87 | myBackground['color'] = pixelColor 88 | myBackground['frequency'] = colors[pixelColor] 89 | 90 | print "colors: ",colors 91 | return [myBackground['color'],myBackground['frequency']],colors 92 | 93 | def getFreqAverage(colors): 94 | sum_c = 0 95 | for e in colors: 96 | sum_c += colors[e] 97 | 98 | average = sum_c/len(colors)*1.0 99 | print "average: ",average 100 | return average 101 | 102 | def paintBackground(originalImg,imgCopy,background,height,width): 103 | for r in xrange(height): 104 | for c in xrange(width): 105 | px_color = originalImg[r,c][0] + originalImg[r,c][1] + originalImg[r,c][2] 106 | Dif = abs(px_color - background[0]) 107 | #print "Dif: ",Dif 108 | if px_color > 10: 109 | 110 | imgCopy[r,c] = 255 111 | return imgCopy 112 | 113 | def getNeighborhood(pixel,height,width): 114 | 115 | neighborhood = [] 116 | 117 | for i in range(pixel[0]-1,pixel[0]+2): 118 | for j in range(pixel[1]-1,pixel[1]+2): 119 | if i < height and j < width and i > 0 and j > 0: 120 | 121 | neighborhood.append([i,j]) 122 | 123 | return neighborhood 124 | 125 | 126 | def applyDFS(img,start,validation,height, width): 127 | visited = [] 128 | stack = [] 129 | point = [] 130 | 131 | point = start 132 | 133 | visited.append(point) 134 | stack.append(point) 135 | 136 | while stack: 137 | 138 | neighborhood = getNeighborhood(point,height,width) 139 | 140 | connexions = [] 141 | for e in neighborhood: 142 | #print "Color img:", img[e[0],e[1]], "against val: ",validation 143 | if e in validation: 144 | if e not in visited: 145 | connexions.append(e) 146 | 147 | if not connexions: 148 | point = stack.pop() 149 | else: 150 | point = max(connexions) 151 | visited.append(point) 152 | stack.append(point) 153 | 154 | return visited 155 | 156 | def drawBoundingBox(figures,originalImg): 157 | print "Drawing bounding-box" 158 | for i in figures: 159 | 160 | i.sort() 161 | n_elem = len(i) 162 | y_min = i[0][0] 163 | y_max = i[n_elem-1][0] 164 | x_min = i[n_elem-1][1] 165 | x_max = 0 166 | 167 | sum_x = 0 168 | sum_y = 0 169 | 170 | for e in i: 171 | sum_x += e[1] 172 | sum_y += e[0] 173 | 174 | if e[1] > x_max: 175 | x_max = e[1] 176 | if e[1] < x_min: 177 | x_min = e[1] 178 | 179 | color = [randint(100,255),randint(0,150),randint(0,255)] 180 | 181 | for z in range(x_min,x_max+1): 182 | originalImg[y_min,z] = color 183 | originalImg[y_max,z] = color 184 | for z in range(y_min,y_max+1): 185 | originalImg[z,x_min] = color 186 | originalImg[z,x_max] = color 187 | 188 | return originalImg 189 | 190 | 191 | def main(): 192 | originalImg = None 193 | img = None 194 | imgCopy = None 195 | height = 0 196 | width = 0 197 | 198 | ColorHist = {} 199 | path = "HoleDetection/img/holeSheet.jpg" 200 | 201 | originalImg, img, imgCopy, height, width = preProcessImg(path) 202 | background,colors = getBackground(originalImg,height,width) 203 | print "Background: ",background 204 | imgCopy = getBorders(path) 205 | 206 | cv2.imwrite("imgCopy.png",imgCopy) 207 | 208 | verticalHist = getVerticalHistogram(height,width,imgCopy) 209 | horizontalHist = getHorizontalHistogram(height,width,imgCopy) 210 | 211 | print "vHist: ",verticalHist 212 | print "hHist: ",horizontalHist 213 | 214 | verticalPeaks = getPeaksByMean(verticalHist) 215 | horizontalPeaks = getPeaksByMean(horizontalHist) 216 | 217 | red = [0,0,255] 218 | blue = [255,0,0] 219 | green = [0,255,0] 220 | 221 | for e in verticalPeaks: 222 | for c in xrange(width): 223 | originalImg[e,c] = green 224 | 225 | for e in horizontalPeaks: 226 | for r in xrange(height): 227 | originalImg[r,e] = blue 228 | 229 | holePeaks = [] 230 | 231 | for v in verticalPeaks: 232 | for h in horizontalPeaks: 233 | if imgCopy[v,h] == 0: 234 | holePeaks.append([v,h]) 235 | originalImg[v,h] = [0,0,255] 236 | 237 | holes = [] 238 | while holePeaks != []: 239 | start = choice(holePeaks) 240 | visited = applyDFS(imgCopy,start,holePeaks,height, width) 241 | holes.append(visited) 242 | for e in visited: 243 | holePeaks.remove(e) 244 | 245 | 246 | 247 | for e in holes: 248 | color = [randint(100,255),randint(100,255),randint(100,255)] 249 | for px in e: 250 | originalImg[px[0],px[1]] = color 251 | 252 | 253 | originalImg = drawBoundingBox(holes,originalImg) 254 | 255 | cv2.imwrite("Peaks.png",originalImg) 256 | 257 | main() 258 | 259 | -------------------------------------------------------------------------------- /LineDetection/img/chess.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/LineDetection/img/chess.png -------------------------------------------------------------------------------- /LineDetection/img/chess_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/LineDetection/img/chess_output.png -------------------------------------------------------------------------------- /LineDetection/img/pedestrianCrossing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/LineDetection/img/pedestrianCrossing.jpg -------------------------------------------------------------------------------- /LineDetection/img/pedestrianCrossing_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/LineDetection/img/pedestrianCrossing_output.png -------------------------------------------------------------------------------- /LineDetection/img/table_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/LineDetection/img/table_1.jpg -------------------------------------------------------------------------------- /LineDetection/img/table_1_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/LineDetection/img/table_1_output.png -------------------------------------------------------------------------------- /LineDetection/img/trainTracks.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/LineDetection/img/trainTracks.jpg -------------------------------------------------------------------------------- /LineDetection/img/trainTracks_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/LineDetection/img/trainTracks_output.png -------------------------------------------------------------------------------- /LineDetection/main.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | from numpy import * 3 | from ShapeDetection import ShapeDetection as sd 4 | import math 5 | from random import randint 6 | 7 | """ 8 | Disclaimer: This code is based on the algorithms provided by Elisa Schaeffer. 9 | Source: http://elisa.dyndns-web.com/teaching/comp/vision/histograma.tar.gz 10 | """ 11 | 12 | def frecuentes(histo, cantidad): 13 | frec = list() 14 | for valor in histo: 15 | if valor is None: 16 | continue 17 | frecuencia = histo[valor] 18 | acepta = False 19 | if len(frec) <= cantidad: 20 | acepta = True 21 | if not acepta: 22 | for (v, f) in frec: 23 | if frecuencia > f: 24 | acepta = True 25 | break 26 | if acepta: 27 | frec.append((valor, frecuencia)) 28 | frec = sorted(frec, key = lambda tupla: tupla[1]) 29 | if len(frec) > cantidad: 30 | frec.pop(0) 31 | incluidos = list() 32 | for (valor, frecuencia) in frec: 33 | incluidos.append(valor) 34 | return incluidos 35 | 36 | #starting 37 | shapeDetector = sd.ShapeDetection() 38 | shapeDetector.test.path = 'LineDetection/'+'train.jpg' 39 | shapeDetector.test.detectBorders() 40 | background = shapeDetector.getBackground() 41 | imagen = shapeDetector.test.originalImg 42 | 43 | 44 | incluir = 1.0 45 | CERO = 0.00001 46 | resultado = list() 47 | index_counter = 0 48 | w=shapeDetector.test.width 49 | h=shapeDetector.test.height 50 | 51 | #Get rho and angle data 52 | for y in xrange(1,h-1,1): 53 | datos = list() 54 | for x in xrange(1,w-1,1): 55 | 56 | if [y,x] in shapeDetector.test.border: 57 | 58 | angulo = shapeDetector.test.borderInfo[index_counter][2] 59 | anguloGrados = angulo*180/math.pi 60 | 61 | print "angulo -> ",angulo," grados: ",anguloGrados 62 | angulo = anguloGrados 63 | if angulo is not None: 64 | rho = (x - w/2) * cos(angulo) + (h/2 - y) * sin(angulo) 65 | datos.append(('%d' % angulo, '%d' % rho)) 66 | else: 67 | datos.append((None, None)) 68 | 69 | index_counter += 1 70 | 71 | else: 72 | datos.append((None,None)) 73 | 74 | resultado.append(datos) 75 | 76 | #Process voting 77 | comb = dict() 78 | for y in xrange(1,len(resultado),1): 79 | for x in xrange(1,len(resultado[y]),1): 80 | if x > 0 and y > 0 and x < w - 1 and y < h - 1: 81 | print "-> y,x: ",y,",",x 82 | (angulo, rho) = resultado[y][x] 83 | if angulo is not None: 84 | combinacion = (angulo, rho) 85 | if combinacion in comb: 86 | comb[combinacion] += 1 87 | else: 88 | comb[combinacion] = 1 89 | 90 | frec = frecuentes(comb, int(ceil(len(comb) * incluir))) 91 | """ 92 | frec = [] 93 | 94 | for i in comb: 95 | if comb[i] > 1: 96 | 97 | frec.append(i) 98 | """ 99 | print "frec: ",frec 100 | 101 | print "Comb: ", comb 102 | 103 | #Draw by angle 104 | for y in xrange(1,len(resultado)-1,1): 105 | renglon = list() 106 | for x in xrange(1,len(resultado[y])-1,1): 107 | (ang, rho) = resultado[y][x] 108 | 109 | if (ang, rho) in frec: 110 | imagen[y,x] = [0,255,0] 111 | 112 | ang = abs(float(ang)) 113 | if ( ang < 100 and ang > 80 ): 114 | 115 | imagen[y,x] = [0,255,0] 116 | elif ang > 0 and ang < 25: 117 | 118 | imagen[y,x] = [0,0,255] 119 | 120 | elif ang < 80 and ang > 25: 121 | imagen[y,x] = [255,100,255] 122 | elif ang > 100 and ang < 135: 123 | imagen[y,x] = [100,100,255] 124 | elif ang > 135 and ang < 155: 125 | imagen[y,x] = [100,100,100] 126 | else: 127 | 128 | imagen[y,x] = [255,0,0] 129 | 130 | 131 | cv2.imwrite("Output_Lines.png",imagen) 132 | 133 | -------------------------------------------------------------------------------- /MeasurementSystem-Project.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem-Project.pdf -------------------------------------------------------------------------------- /MeasurementSystem/Final_Presentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Final_Presentation.pdf -------------------------------------------------------------------------------- /MeasurementSystem/GUI.py: -------------------------------------------------------------------------------- 1 | import sys,pygame 2 | from MeasurementSystem import * 3 | from tkFileDialog import * 4 | 5 | def loadFile(): 6 | fname = "" 7 | try: 8 | fname = askopenfilename(filetypes=(("All files", "*.*"), 9 | ("PNG", "*.png"))) 10 | 11 | except ValueError: 12 | print "Please select an image. Try again..." 13 | 14 | return fname 15 | 16 | pygame.init() 17 | imgPath = loadFile() 18 | image = pygame.image.load(imgPath) 19 | 20 | imagerect = image.get_rect() 21 | realWidth, realHeight = imagerect.size 22 | 23 | scaleWidth, scaleHeight = 400,600 24 | image = pygame.transform.scale(image,(scaleWidth,scaleHeight)) 25 | 26 | imagerect = image.get_rect() 27 | width, height = imagerect.size 28 | 29 | panel = 90 30 | topPanel = 40 31 | 32 | size = ((width+panel),(height+topPanel)) 33 | screen = pygame.display.set_mode(size) 34 | 35 | pygame.display.set_caption("Measurement System") 36 | font = pygame.font.Font(None, 20) 37 | 38 | #Options to display 39 | btnFindObjects = font.render('Find Objects',1,(0,0,250)) 40 | btnMeasureCm = font.render('Measure (cm)',1,(0,255,0)) 41 | btnMeasureIn = font.render('Measure (in)',1,(0,255,0)) 42 | btnMeasureMm = font.render('Measure (mm)',1,(0,255,0)) 43 | btnMeasureLine = font.render('Measure (line)',1,(0,255,0)) 44 | 45 | found = False 46 | isReadyToMeasure = False 47 | message = font.render('',1,(255,0,0)) 48 | isObject = False 49 | objectIndex = int() 50 | isWaiting2P = False 51 | 52 | scaleW, scaleH = int(),int() 53 | 54 | point1, point2 = (0,0) 55 | counter = 0 56 | 57 | global contourBoxes 58 | 59 | while 1: 60 | for event in pygame.event.get(): 61 | if event.type == pygame.QUIT: sys.exit() 62 | 63 | if event.type == pygame.MOUSEBUTTONDOWN: 64 | cordx, cordy = pygame.mouse.get_pos() 65 | if 0 < cordx < panel and topPanel < cordy < 25+topPanel: #Find Shapes 66 | print "btnFindObjects" 67 | print "Select an object as reference" 68 | message = font.render('Select an object as reference',1,(255,0,0)) 69 | found = True 70 | 71 | contourBoxes = FindShapes(imgPath) 72 | 73 | image = pygame.image.load("RESULT.png") 74 | image = pygame.transform.scale(image,(400,600)) 75 | 76 | 77 | if 0 < cordx < panel and (35+topPanel) < cordy < (55+topPanel): #measure in cm 78 | 79 | if found and isObject and objectIndex >= 0: 80 | print "objectIndex: ",objectIndex 81 | Measure(objectIndex,contourBoxes,"cm") 82 | 83 | image = pygame.image.load("RESULT.png") 84 | image = pygame.transform.scale(image,(scaleWidth,scaleHeight)) 85 | message = font.render("Measurement complete",1,(255,0,0)) 86 | 87 | else: 88 | print "Select an object" 89 | message = font.render("Select an object",1,(255,0,0)) 90 | 91 | if 0 < cordx < panel and (topPanel*3) < cordy < (topPanel*3+20): #measure in inches 92 | 93 | if found and isObject and objectIndex >= 0: 94 | print "objectIndex: ",objectIndex 95 | Measure(objectIndex,contourBoxes,"in") 96 | 97 | image = pygame.image.load("RESULT.png") 98 | image = pygame.transform.scale(image,(scaleWidth,scaleHeight)) 99 | message = font.render("Measurement complete",1,(255,0,0)) 100 | 101 | else: 102 | print "Select an object" 103 | message = font.render("Select an object",1,(255,0,0)) 104 | 105 | 106 | if 0 < cordx < panel and (topPanel*4) < cordy < (topPanel*4+20): #measure in mm 107 | 108 | if found and isObject and objectIndex >= 0: 109 | print "objectIndex: ",objectIndex 110 | Measure(objectIndex,contourBoxes,"mm") 111 | 112 | image = pygame.image.load("RESULT.png") 113 | image = pygame.transform.scale(image,(scaleWidth,scaleHeight)) 114 | message = font.render("Measurement complete",1,(255,0,0)) 115 | 116 | else: 117 | print "Select an object" 118 | message = font.render("Select an object",1,(255,0,0)) 119 | 120 | if 0 < cordx < panel and (topPanel*5) < cordy < (topPanel*5+20): #measure line 121 | 122 | if found and isObject and objectIndex >= 0: 123 | print "objectIndex: ",objectIndex 124 | message = font.render("Select 2 points",1,(255,0,0)) 125 | isWaiting2P = True 126 | 127 | 128 | else: 129 | print "Select an object" 130 | message = font.render("Select an object as reference",1,(255,0,0)) 131 | 132 | 133 | if panel < cordx < (width+panel) and topPanel < cordy < (height+topPanel): #Selecting an object as reference 134 | if found and (not isWaiting2P): 135 | print "Checking if it is an object" 136 | 137 | print "w and h ", width,realWidth,height,realHeight 138 | scaleW = (realWidth*1.0)/width 139 | scaleH = (realHeight*1.0)/height 140 | #print "scales: ",scaleW,scaleH 141 | isObject,objectIndex = getReferenceObject((cordx-panel,cordy-topPanel),contourBoxes,scaleW,scaleH) 142 | msgString = "" 143 | 144 | if isObject: 145 | msgString = "Object selected" 146 | else: 147 | msgString = "Select an object as reference" 148 | 149 | message = font.render(msgString,1,(255,0,0)) 150 | 151 | image = pygame.image.load("RESULT.png") 152 | image = pygame.transform.scale(image,(400,600)) 153 | 154 | else: 155 | if found and isObject and objectIndex >= 0: 156 | if counter == 0: 157 | point1 = (cordx-panel,cordy-topPanel) 158 | counter += 1 159 | DrawPoint((point1[0],point1[1]),scaleW,scaleH) 160 | 161 | elif counter == 1: 162 | point2 = (cordx-panel,cordy-topPanel) 163 | DrawPoint((point2[0],point2[1]),scaleW,scaleH) 164 | counter += 1 165 | 166 | if counter == 2: 167 | counter = 0 168 | print "points: ",point1,point2 169 | isWaiting2P = False 170 | MeasureLine(contourBoxes,objectIndex,point1,point2,scaleW,scaleH,"in") 171 | 172 | image = pygame.image.load("RESULT.png") 173 | image = pygame.transform.scale(image,(scaleWidth,scaleHeight)) 174 | 175 | else: 176 | print "You must find shapes and then select an object" 177 | message = font.render('You must find shapes first',1,(255,0,0)) 178 | 179 | 180 | 181 | screen.fill((0,0,0)) 182 | screen.blit(image,(panel,topPanel)) 183 | screen.blit(message,(200,15)) 184 | screen.blit(btnFindObjects,(0,topPanel)) 185 | screen.blit(btnMeasureCm,(0,topPanel*2)) 186 | screen.blit(btnMeasureIn,(0,topPanel*3)) 187 | screen.blit(btnMeasureMm,(0,topPanel*4)) 188 | screen.blit(btnMeasureLine,(0,topPanel*5)) 189 | 190 | pygame.display.flip() 191 | -------------------------------------------------------------------------------- /MeasurementSystem/MeasurementSystem.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | from matplotlib import pyplot as plt 4 | from random import choice,randint 5 | import math 6 | 7 | global img 8 | global imgCopy 9 | global height, width 10 | 11 | def filter_image(img): 12 | #source: http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html#thresholding 13 | #Process using Otsu's thresholding after Gaussian filtering 14 | blur = cv2.GaussianBlur(img,(5,5),0) 15 | 16 | cv2.imwrite('blur.png',blur) 17 | ret,th = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) 18 | return ret,th 19 | 20 | def get_contours(th): 21 | #Find contours based on the threshold obtained 22 | contours, hierarchy = cv2.findContours(th,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 23 | return contours 24 | 25 | def get_histogram_contours(contours): 26 | hist_contours = [] 27 | contours_array = [] 28 | #I use the area of the bounding box in order to discard them by it later on 29 | for i in range(len(contours)): 30 | 31 | contour = contours[i] 32 | rect = cv2.minAreaRect(contour) 33 | box = cv2.cv.BoxPoints(rect) 34 | box = np.int0(box) 35 | side = [ 36 | math.hypot(box[1][0] - box[0][0], box[1][1] - box[0][1]), 37 | math.hypot(box[3][0] - box[0][0], box[3][1] - box[0][1]) 38 | ] 39 | area = side[0]*side[1] 40 | hist_contours.append(float("{0:.2f}".format(area))) 41 | contours_array.append(box) 42 | 43 | #print "hist_contours: ",hist_contours 44 | return hist_contours,contours_array 45 | 46 | def basic_global_thresholding(histogram): 47 | #Basic global thresholding 48 | t_new = max(histogram)/2.0 #the threshold should be close to the center 49 | t_old = 0.0 50 | mean = [0,0] 51 | T = 0 52 | while abs(t_old-t_new) > 0.001: #the loop ends until the difference of the old threshold and the new one is minimum 53 | 54 | mean = get_averages(histogram,t_new) #get the average of each side based on the current threshold 55 | t_old = t_new 56 | t_new = 0.5*(mean[0]+mean[1]) # get a new threshold by obtaining the average of the means 57 | 58 | T = t_new/2.5 59 | 60 | return T-T*.95 #After testing this kind of threshold gave me good results 61 | 62 | def discard_contours(histogram,contours,T): 63 | contours_filtered = [] 64 | #Only those greater than the Threshold will be taken into account 65 | for i in range(len(contours)): 66 | if histogram[i] > T: 67 | contours_filtered.append(contours[i]) 68 | #print "average selected: ",histogram[i] 69 | return contours_filtered 70 | 71 | 72 | def get_averages(histogram,t): 73 | 74 | sum_upper = 0 75 | counter_upper = 0 76 | 77 | sum_down = 0 78 | counter_down = 0 79 | for e in histogram: 80 | if e > t: #sum all the gradients > threshold 81 | sum_upper += e 82 | counter_upper += 1 83 | else: #sum all the gradients < threshold 84 | sum_down += e 85 | counter_down += 1 86 | 87 | return [(sum_upper/counter_upper*1.0),(sum_down/counter_down*1.0)] #return means 88 | 89 | def draw_bounding_boxes(imgCopy,contourBoxes,thickness): 90 | counter = 0 91 | for e in contourBoxes: 92 | color = [randint(100,255),randint(0,150),randint(0,255)] 93 | cv2.drawContours(imgCopy,[e],-1,color,thickness) 94 | set_label(imgCopy,"Shape "+str(counter), e[1]) 95 | counter+=1 96 | 97 | 98 | def set_label(imgCopy,text,coordinate): 99 | label = text 100 | cv2.putText(imgCopy,label, (coordinate[0], coordinate[1]-20), cv2.FONT_HERSHEY_SIMPLEX, 2, (70,70,240),5) 101 | 102 | 103 | def draw_corner_points(imgCopy,box,thickness,black): 104 | 105 | colors = [[0,0,255],[0,255,0],[255,0,0],[155,155,155]] 106 | counter = 0 107 | for e in box: 108 | color_box = [randint(100,255),randint(0,150),randint(0,255)] 109 | for x in range(e[0]-thickness,e[0]+thickness): 110 | for y in range(e[1]-thickness,e[1]+thickness): 111 | if x < width and y < height: 112 | if black: 113 | imgCopy[y,x] = [0,0,0] 114 | else: 115 | imgCopy[y,x] = [0,255,0] 116 | 117 | 118 | 119 | def get_reference_objectByColor(imgCopy,contours): 120 | shape_colors = [] 121 | for e in contours: 122 | colors = [] 123 | for x in range(e[1][0],e[2][0]): 124 | for y in range(e[1][1],e[3][1]): 125 | colors.append([imgCopy[y,x][0],imgCopy[y,x][1],imgCopy[y,x][2]]) 126 | shape_colors.append(colors) 127 | 128 | counter = [] 129 | for e in shape_colors: 130 | counter_sc = 0 131 | for i in e: 132 | 133 | if i[2] > 100 and i[1] < 100 and i[0] < 100: 134 | counter_sc += 1 135 | 136 | counter.append(counter_sc) 137 | 138 | #print "Counter-colors-shape: ",counter 139 | 140 | max_value = max(counter) 141 | shape_index = -1 142 | for i in range(len(counter)): 143 | if counter[i] == max_value: 144 | shape_index = i 145 | 146 | #print "shape index: ",shape_index 147 | 148 | def getLimits(box): 149 | xmin = box[0][0] 150 | xmax = box[0][0] 151 | ymin = box[0][1] 152 | ymax = box[0][1] 153 | 154 | for e in box: 155 | if e[0] < xmin: 156 | xmin = e[0] 157 | if e[0] > xmax: 158 | xmax = e[0] 159 | if e[1] < ymin: 160 | ymin = e[1] 161 | if e[1] > ymax: 162 | ymax = e[1] 163 | #print "xmin,xmax,ymin,ymax: ",xmin,xmax,ymin,ymax 164 | return xmin,xmax,ymin,ymax 165 | 166 | def getReferenceObject(coord,contourBoxes,scaleW,scaleH): 167 | print "coord: ",coord 168 | coord = coord[0]*scaleW,coord[1]*scaleH 169 | resultImg = cv2.imread("RESULT.png") 170 | found = False 171 | index = -1 172 | counter = 0 173 | for box in contourBoxes: 174 | xmin,xmax,ymin,ymax = getLimits(box) 175 | #print "BOX: ",box 176 | if xmin < coord[0] and ymin < coord[1] and coord[0] < xmax and coord[1] < ymax : 177 | #print "coord in box - " 178 | found = True 179 | index = counter 180 | cv2.drawContours(resultImg,[box],-1,(0,0,255),25) 181 | 182 | else: 183 | #print "coord NOT IN box -" 184 | cv2.drawContours(resultImg,[box],-1,(255,0,0),25) 185 | 186 | counter += 1 187 | print "validation: ",(xmin,ymin)," - ",(xmax,ymax), "coord: ",coord 188 | 189 | cv2.imwrite("RESULT.png",resultImg) 190 | 191 | return found,index 192 | 193 | def DrawPoint(point,scaleW,scaleH): 194 | point = int(point[0]*scaleW),int(point[1]*scaleH) 195 | resultImg = cv2.imread("RESULT.png") 196 | cv2.circle(resultImg,point,20,(0,255,0),15) 197 | cv2.imwrite("RESULT.png",resultImg) 198 | 199 | def MeasureLine(contourBoxes,objectIndex,point1,point2,scaleW,scaleH,unit): 200 | resultImg = cv2.imread("RESULT.png") 201 | 202 | box = contourBoxes[objectIndex] 203 | boxDist = math.hypot(box[1][0] - box[0][0], box[1][1] - box[0][1]) 204 | 205 | point1 = int(point1[0]*scaleW),int(point1[1]*scaleH) 206 | point2 = int(point2[0]*scaleW),int(point2[1]*scaleH) 207 | 208 | dist = math.hypot(abs(point1[0]-point2[0]),abs(point1[1]-point2[1])) 209 | baseMeasure = 4.0#cm ... I already know the measure of my object as reference 210 | inches = 0.393700787 211 | distR = (dist*baseMeasure/boxDist) 212 | label = str(float("{0:.1f}".format(distR*inches))) 213 | 214 | label = label+" in" 215 | 216 | cv2.line(resultImg, (point1), (point2), (0,255,0),10) 217 | cv2.putText(resultImg,label,point1, cv2.FONT_HERSHEY_SIMPLEX, 2, (0,0,250),5) 218 | 219 | cv2.imwrite("RESULT.png",resultImg) 220 | 221 | def Measure(objectIndex,contourBoxes,unit): 222 | dist = [] 223 | box = contourBoxes[objectIndex] 224 | dist.append(math.hypot(box[1][0] - box[0][0], box[1][1] - box[0][1])) 225 | dist.append(math.hypot(box[3][0] - box[0][0], box[3][1] - box[0][1])) 226 | baseMeasure = 4.0 #cm ... I already know the measure of my object as reference 227 | 228 | resultImg = cv2.imread("RESULT.png") 229 | 230 | for i in range(len(contourBoxes)): 231 | if i != objectIndex or 1 == 1: 232 | 233 | boxDist = [] 234 | boxToMeasure = contourBoxes[i] 235 | boxDist.append(math.hypot(boxToMeasure[1][0] - boxToMeasure[0][0], boxToMeasure[1][1] - boxToMeasure[0][1])) 236 | boxDist.append(math.hypot(boxToMeasure[3][0] - boxToMeasure[0][0], boxToMeasure[3][1] - boxToMeasure[0][1])) 237 | 238 | 239 | 240 | width = boxDist[0]*baseMeasure/dist[0] 241 | height = boxDist[1]*baseMeasure/dist[1] 242 | 243 | label1 = str(float("{0:.1f}".format(height))) 244 | label2 = str(float("{0:.1f}".format(width))) 245 | 246 | if unit == "cm": 247 | label = label1 + " X " + label2+" cm" 248 | else: 249 | if unit == "in": 250 | inches = 0.393700787 251 | label1 = str(float("{0:.1f}".format(height*inches))) 252 | label2 = str(float("{0:.1f}".format(width*inches))) 253 | 254 | if unit == "mm": 255 | mm = 10 256 | label1 = str(float("{0:.1f}".format(height*mm))) 257 | label2 = str(float("{0:.1f}".format(width*mm))) 258 | 259 | label = label1 + " X "+label2+" "+unit 260 | 261 | labelSize = len(label)*15 262 | xmin,xmax,ymin,ymax = getLimits(boxToMeasure) 263 | cv2.putText(resultImg,label, (xmin + int(abs(xmax-xmin)/2)-labelSize,ymin+int(abs(ymax-ymin)/2)), cv2.FONT_HERSHEY_SIMPLEX, 2, (0,130,255),5) 264 | 265 | cv2.imwrite("RESULT.png",resultImg) 266 | 267 | return 268 | 269 | def FindShapes(ip): 270 | imgPath = ip 271 | img = cv2.imread(imgPath,0) 272 | imgCopy = cv2.imread(imgPath) 273 | height, width = img.shape 274 | 275 | 276 | ret, th = filter_image(img) 277 | 278 | cv2.imwrite('RESULT_0.png',th) 279 | 280 | contours, hierarchy = cv2.findContours(th,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 281 | #print "Contours: ",contours 282 | 283 | #print "len(contours): ",len(contours) 284 | 285 | hist_c,contours_array = get_histogram_contours(contours) 286 | 287 | t = basic_global_thresholding(hist_c) 288 | #print "t_hist: ",t 289 | contourBoxes = discard_contours(hist_c,contours_array,t) 290 | contourBoxes.pop(0) #delete the box of the background 291 | #print "contour boxes: ",contourBoxes 292 | 293 | draw_bounding_boxes(imgCopy,contourBoxes,15) 294 | 295 | cv2.imwrite('RESULT.png',imgCopy) 296 | 297 | return contourBoxes 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | -------------------------------------------------------------------------------- /MeasurementSystem/README.md: -------------------------------------------------------------------------------- 1 | #Project: Measurement System 2 | 3 | This program needs python 2.7, pygame 1.9 and opencv 2.4 4 | 5 | MeasurementSystem/GUI.py This is the Graphical User Interface of the program 6 | 7 | MeasurementSystem/MeasurementSystem.py This contains all the functions to handle the image and measure stuff 8 | 9 | To run it, execute: python GUI.py -------------------------------------------------------------------------------- /MeasurementSystem/Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Report.pdf -------------------------------------------------------------------------------- /MeasurementSystem/Tests/INPUT/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/INPUT/0.jpg -------------------------------------------------------------------------------- /MeasurementSystem/Tests/INPUT/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/INPUT/1.jpg -------------------------------------------------------------------------------- /MeasurementSystem/Tests/INPUT/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/INPUT/2.jpg -------------------------------------------------------------------------------- /MeasurementSystem/Tests/INPUT/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/INPUT/3.jpg -------------------------------------------------------------------------------- /MeasurementSystem/Tests/INPUT/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/INPUT/4.jpg -------------------------------------------------------------------------------- /MeasurementSystem/Tests/OUTPUT/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/OUTPUT/0.png -------------------------------------------------------------------------------- /MeasurementSystem/Tests/OUTPUT/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/OUTPUT/1.png -------------------------------------------------------------------------------- /MeasurementSystem/Tests/OUTPUT/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/OUTPUT/2.png -------------------------------------------------------------------------------- /MeasurementSystem/Tests/OUTPUT/2pointsGiven.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/OUTPUT/2pointsGiven.png -------------------------------------------------------------------------------- /MeasurementSystem/Tests/OUTPUT/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/OUTPUT/3.png -------------------------------------------------------------------------------- /MeasurementSystem/Tests/OUTPUT/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/OUTPUT/4.png -------------------------------------------------------------------------------- /MeasurementSystem/Tests/video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/MeasurementSystem/Tests/video.mp4 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ComputerVision 2 | 3 | Project: Measurement System 4 | 5 | This program needs python 2.7, pygame 1.9 and opencv 2.4 6 | 7 | 8 | MeasurementSystem/GUI.py 9 | This is the Graphical User Interface of the program 10 | 11 | 12 | MeasurementSystem/MeasurementSystem.py 13 | This contains all the functions to handle the image and measure stuff 14 | 15 | 16 | To run it, execute: 17 | python GUI.py -------------------------------------------------------------------------------- /ShapeDetection/ShapeDetection.py: -------------------------------------------------------------------------------- 1 | from EdgeDetection import EdgeDetection as ed 2 | class ShapeDetection: 3 | 4 | def __init__(self): 5 | 6 | self.myBackground = 0 7 | self.test = ed.EdgeDetection() 8 | 9 | if self.test.debug: 10 | print "-> preprocessing the image" 11 | 12 | self.test.path = "" 13 | 14 | def getNeighborhood(self,pixel): 15 | 16 | neighborhood = [] 17 | 18 | for i in range(pixel[0]-1,pixel[0]+2): 19 | for j in range(pixel[1]-1,pixel[1]+2): 20 | if i < self.test.height and j < self.test.width and i > 0 and j > 0: 21 | 22 | neighborhood.append([i,j]) 23 | 24 | return neighborhood 25 | 26 | def isColor(self,pixel,color): 27 | 28 | print "pixel: ",pixel 29 | print "color: ",color 30 | pixelColor = str(pixel[0])+str(pixel[1])+str(pixel[2]) 31 | 32 | return pixelColor == color 33 | 34 | def getBackground(self): 35 | 36 | colors = {} 37 | myBackground = {'color': 0, 'frecuency':0} 38 | 39 | for r in range(self.test.height-1): 40 | for c in range(self.test.width-1): 41 | pixelColor = str(self.test.originalImg[r,c][0])+str(self.test.originalImg[r,c][1])+str(self.test.originalImg[r,c][2]) 42 | 43 | if pixelColor not in colors: 44 | 45 | colors[pixelColor] = 1 46 | 47 | if myBackground['color'] == 0: 48 | myBackground['color'] = pixelColor 49 | myBackground['frequency'] = 1 50 | else: 51 | colors[pixelColor] += 1 52 | 53 | if colors[pixelColor] > myBackground['frequency']: 54 | myBackground['color'] = pixelColor 55 | myBackground['frequency'] = colors[pixelColor] 56 | 57 | return myBackground['color'] 58 | 59 | def detectFigures(self): 60 | 61 | self.test.detectBorders() 62 | 63 | self.myBackground = self.getBackground() 64 | 65 | figures = [] 66 | 67 | while self.test.border: 68 | detected = self.applyDFS(self.test,self.test.border,self.myBackground) 69 | figures.append(detected) 70 | 71 | for i in detected: 72 | self.test.imgCopy[i[0],i[1]] = 100 73 | if [i[0],i[1]] in self.test.border: 74 | self.test.border.remove([i[0],i[1]]) 75 | 76 | return figures 77 | 78 | def applyDFS(self,test,borders,myBackground): 79 | visited = [] 80 | stack = [] 81 | point = [] 82 | 83 | point = borders[0] 84 | 85 | visited.append(point) 86 | stack.append(point) 87 | 88 | while stack: 89 | 90 | neighborhood = self.getNeighborhood(point) 91 | 92 | connexions = [] 93 | for e in neighborhood: 94 | 95 | if e in borders or not self.isColor(test.originalImg[e[0],e[1]], str(myBackground)): 96 | if e not in visited: 97 | connexions.append(e) 98 | 99 | 100 | if not connexions: 101 | point = stack.pop() 102 | else: 103 | point = max(connexions) 104 | visited.append(point) 105 | stack.append(point) 106 | 107 | return visited 108 | 109 | 110 | def paintBorder(self): 111 | for r in range(1,self.test.height-1,1): 112 | for c in range(1,self.test.width-1,1): 113 | if [r,c] in self.test.border: 114 | self.test.imgCopy[r,c] = 255 115 | else: 116 | self.test.imgCopy[r,c] = 0 117 | 118 | def drawBoundingBox(self,figures): 119 | print "Drawing bounding-box" 120 | for i in figures: 121 | 122 | i.sort() 123 | n_elem = len(i) 124 | y_min = i[0][0] 125 | y_max = i[n_elem-1][0] 126 | x_min = i[n_elem-1][1] 127 | x_max = 0 128 | 129 | sum_x = 0 130 | sum_y = 0 131 | 132 | for e in i: 133 | sum_x += e[1] 134 | sum_y += e[0] 135 | 136 | if e[1] > x_max: 137 | x_max = e[1] 138 | if e[1] < x_min: 139 | x_min = e[1] 140 | 141 | color = [0,255,0] 142 | 143 | for z in range(x_min,x_max+1): 144 | self.test.originalImg[y_min,z] = color 145 | self.test.originalImg[y_max,z] = color 146 | for z in range(y_min,y_max+1): 147 | self.test.originalImg[z,x_min] = color 148 | self.test.originalImg[z,x_max] = color 149 | 150 | centerOfMass = [sum_y/n_elem,sum_x/n_elem] 151 | 152 | self.test.originalImg[centerOfMass[0],centerOfMass[1]] = [0,0,255] 153 | -------------------------------------------------------------------------------- /ShapeDetection/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/ShapeDetection/__init__.py -------------------------------------------------------------------------------- /ShapeDetection/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/ShapeDetection/__init__.pyc -------------------------------------------------------------------------------- /ShapeDetection/img_testing/centerOfMass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/ShapeDetection/img_testing/centerOfMass.png -------------------------------------------------------------------------------- /ShapeDetection/img_testing/coins_original.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/ShapeDetection/img_testing/coins_original.jpg -------------------------------------------------------------------------------- /ShapeDetection/img_testing/findingForms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/ShapeDetection/img_testing/findingForms.png -------------------------------------------------------------------------------- /ShapeDetection/img_testing/other_figures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/ShapeDetection/img_testing/other_figures.png -------------------------------------------------------------------------------- /ShapeDetection/img_testing/other_figures_modified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/ShapeDetection/img_testing/other_figures_modified.png -------------------------------------------------------------------------------- /ShapeDetection/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import cv2 4 | from Tkinter import * 5 | from tkFileDialog import * 6 | import sys 7 | from numpy import * 8 | 9 | from ShapeDetection import ShapeDetection as sd 10 | import random 11 | 12 | def execute(): 13 | 14 | shapeDetector = sd.ShapeDetection() 15 | 16 | shapeDetector.test.path = loadFile() 17 | 18 | figures = shapeDetector.detectFigures() 19 | 20 | shapeDetector.drawBoundingBox(figures) 21 | 22 | cv2.imwrite("result2.png",shapeDetector.test.originalImg) 23 | 24 | del shapeDetector.test.histogram[:] # remove all the elements in the histogram 25 | 26 | print "-> You can choose another image ..." 27 | 28 | 29 | def loadFile(): 30 | fname = "" 31 | try: 32 | fname = askopenfilename(filetypes=(("All files", "*.*"), 33 | ("PNG", "*.png"))) 34 | 35 | except ValueError: 36 | print "Please select an image. Try again..." 37 | 38 | return fname 39 | 40 | 41 | master = Tk() 42 | 43 | f = Frame(master, height=300, width=300) 44 | f.pack_propagate(0) 45 | f.pack() 46 | 47 | b = Button(f, text="Load a picture", command = execute) 48 | b.pack() 49 | 50 | master.title("Edge detection") 51 | mainloop() 52 | -------------------------------------------------------------------------------- /findingThings/main.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | colors = {} 4 | myBackground = {'color':0,'frequency':0} 5 | 6 | def findColors(): 7 | #print "Findcolors " 8 | for i in range(height): 9 | for j in range(width): 10 | 11 | pixelColor = str(img[i,j][0])+str(img[i,j][1])+str(img[i,j][2]) 12 | 13 | if pixelColor not in colors: 14 | 15 | colors[pixelColor] = 1 16 | 17 | if myBackground['color'] == 0: 18 | myBackground['color'] = pixelColor 19 | myBackground['frequency'] = 1 20 | else: 21 | colors[pixelColor] += 1 22 | 23 | if colors[pixelColor] > myBackground['frequency']: 24 | myBackground['color'] = pixelColor 25 | myBackground['frequency'] = colors[pixelColor] 26 | 27 | return 28 | 29 | 30 | def isColor(pixel,color): 31 | pixelColor = str(pixel[0])+str(pixel[1])+str(pixel[2]) 32 | return pixelColor == color 33 | 34 | 35 | def getNeighbors(position): 36 | 37 | neighbors = [] 38 | for i in range(position[0]-1,position[0]+2): 39 | for j in range(position[1]-1, position[1]+2): 40 | if [i,j] != [position[0],position[1]] and i < height and j < width: 41 | neighbors.append([i,j]) 42 | 43 | neighbors.sort() 44 | 45 | return neighbors 46 | 47 | 48 | coordinates = [] 49 | def findForm(): 50 | print "findForm" 51 | for i in range(height): 52 | for j in range(width): 53 | if not isColor(img[i,j],myBackground['color']): 54 | img[i,j] = [0,255,0] 55 | coordinates.append([i,j]) 56 | 57 | return 58 | 59 | 60 | border = [] 61 | def paintBorder(): 62 | for c in coordinates: 63 | neighborhood = getNeighbors(c) 64 | hasBackground = 0 65 | hasGreen = 0 66 | for n in neighborhood: 67 | if isColor(img[n[0],n[1]],myBackground['color']): 68 | hasBackground += 1 69 | if isColor(img[n[0],n[1]],"02550"): 70 | hasGreen += 1 71 | if hasBackground > 0 and hasGreen > 2: 72 | img[c[0],c[1]] = [0,0,0] 73 | border.append(c) 74 | 75 | def pointX(): 76 | for c in coordinates: 77 | neighborhood = getNeighbors(c) 78 | counter = 0 79 | for n in neighborhood: 80 | #print n 81 | if isColor(img[n[0],n[1]],"02550"): 82 | counter += 1 83 | if counter == 8: 84 | return c 85 | 86 | def pointX2(p1,p2): #still for testing 87 | for c in coordinates: 88 | if not (c > [28,43] and c < [59,78]): 89 | 90 | neighborhood = getNeighbors(c) 91 | counter = 0 92 | for n in neighborhood: 93 | #print n 94 | if isColor(img[n[0],n[1]],"02550"): 95 | counter += 1 96 | if counter == 8: 97 | img[c[0],c[1]] = [255,0,0] 98 | return c 99 | 100 | 101 | myObject = [] 102 | def findingObject(): 103 | start = [] 104 | nextOne = [] 105 | caught = 0 106 | 107 | old_len = 0 108 | 109 | while caught <= 2: 110 | 111 | if nextOne: 112 | neighborhood = getNeighbors(nextOne) 113 | if caught > 1: 114 | print "nextOne: ",nextOne," neighborhood: ",neighborhood 115 | else: 116 | pX = pointX() 117 | neighborhood = getNeighbors([pX[0]-1,pX[1]-1]) 118 | 119 | hasBlack = 0 120 | hasGreen = 0 121 | 122 | old_len = len(myObject) 123 | 124 | for n in neighborhood: 125 | if n in border and n not in myObject: 126 | img[n[0],n[1]] = [0,0,255] 127 | myObject.append(n) 128 | 129 | #if old len of myObject is equal to the current one, so it's caught in the loop 130 | if old_len == len(myObject): 131 | print "caught" 132 | caught += 1 133 | l = len(myObject) 134 | nextOne = myObject[l-caught] 135 | 136 | else: 137 | l = len(myObject) 138 | nextOne = myObject[l-1] 139 | 140 | print myObject 141 | print "len_myObject: ", len(myObject)," len_border: ", len(border) 142 | 143 | 144 | 145 | point1 = [] 146 | point2 = [] 147 | def drawBox(): 148 | 149 | myObject.sort() 150 | length = len(myObject) 151 | 152 | print "myObject: ", myObject 153 | 154 | xMin, yMin = myObject[0] 155 | xMax, yMax = myObject[length-1] 156 | 157 | print "xMin: ",xMin," yMin:",yMin," xMax:",xMax," yMax:",yMax 158 | 159 | point1 = [xMin,yMin] 160 | point2 = [xMax,yMax] 161 | 162 | for e in myObject: 163 | if e[1] < yMin: 164 | yMin = e[1] 165 | if e[1] > yMax: 166 | yMax = e[1] 167 | 168 | for x in range(xMin,xMax,1): 169 | img2[x,yMin] = [0,0,255] 170 | img2[x,yMax] = [0,0,255] 171 | for y in range(yMin,yMax,1): 172 | img2[xMin,y] = [0,0,255] 173 | img2[xMax,y] = [0,0,255] 174 | 175 | 176 | #Image properties 177 | path = "pictures/" 178 | filename = "circle.jpg" 179 | 180 | img = cv2.imread(path+filename) #picture as a buffer 181 | img2 = cv2.imread(path+filename) #final picture 182 | height, width, depth = img.shape 183 | 184 | def main(): 185 | findColors() 186 | findForm() 187 | paintBorder() 188 | findingObject() 189 | 190 | drawBox() 191 | 192 | #findingObject() 193 | 194 | cv2.imwrite(path+"result.jpg",img2) 195 | #cv2.imshow('image',img) 196 | cv2.imshow('image',img2) 197 | cv2.waitKey(0) 198 | cv2.destroyAllWindows() 199 | 200 | 201 | main() 202 | -------------------------------------------------------------------------------- /findingThings/pictures/circle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/findingThings/pictures/circle.jpg -------------------------------------------------------------------------------- /findingThings/pictures/circle2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Constantino/ComputerVision/44d9b884e564968bfd3472f50ffc41122ec9c5a7/findingThings/pictures/circle2.jpg --------------------------------------------------------------------------------