diff --git a/PiVideoStream.py b/PiVideoStream.py index 185417f..47237c2 100755 --- a/PiVideoStream.py +++ b/PiVideoStream.py @@ -14,8 +14,24 @@ class PiVideoStream: self.camera.exposure_mode = 'auto' # self.camera.image_effect = 'colorbalance' # self.camera.image_effect_params = (0,1,1,1,0,0) + self.camera.exposure_mode = 'auto' + self.camera.awb_mode = 'off' + self.camera.awb_gains = (1.5, 1.5) +# self.camera.analog_gain = 1.75 +# self.camera.digital_gain = 1.00 + self.rawCapture = PiRGBArray(self.camera, size=resolution) + self.stream = self.camera.capture_continuous(self.rawCapture, + format="bgr", use_video_port=True) + # initialize the frame and the variable used to indicate + # if the thread should be stopped + self.frame = None + self.stopped = False + self.fps = None + self.thread = None + self.startup = True + def printSettings(self): awb_gains = self.camera.awb_gains print ("sensor_mode : " + str(self.camera.sensor_mode)) print ("resolution : " + str(self.camera.resolution)) @@ -38,18 +54,6 @@ class PiVideoStream: print ("image_effect_params : " + str(self.camera.image_effect_params)) print ("sharpness : " + str(self.camera.sharpness)) - self.rawCapture = PiRGBArray(self.camera, size=resolution) - self.stream = self.camera.capture_continuous(self.rawCapture, - format="bgr", use_video_port=True) - - # initialize the frame and the variable used to indicate - # if the thread should be stopped - self.frame = None - self.stopped = False - self.fps = None - self.thread = None - self.startup = True - def start(self): # start the thread to read frames from the video stream self.thread = Thread(target=self.update, args=()) @@ -59,6 +63,11 @@ class PiVideoStream: def update(self): # keep looping infinitely until the thread is stopped for f in self.stream: + if self.camera.exposure_mode == 'auto': + if self.camera.analog_gain > 1.75 and self.camera.digital_gain == 1.0: + self.camera.exposure_mode = 'off' + self.printSettings() + if self.startup: self.fps = FPS().start() self.startup = False diff --git a/beadDetect.py b/beadDetect.py index 8af9c3c..003c26b 100755 --- a/beadDetect.py +++ b/beadDetect.py @@ -62,56 +62,59 @@ class FindObjects(): temp_objects = [] objectsCandIds = [] - if hierachy is not None: - while count != -1: - family = FindObjects.getFamily([], count, hierachy) + try: + if hierachy.any(): + while count != -1: + family = FindObjects.getFamily([], count, hierachy) - dupDict = {} - members = [] - for member in family: - x,y,w,h = cv2.boundingRect(contours[member]); - key = str([x,y,w,h]) + '.key' - if not key in dupDict: - dupDict[key] = member - members.append({ 'id' : member, 'bbox' : [x,y,w,h]}) + dupDict = {} + members = [] + for member in family: + x,y,w,h = cv2.boundingRect(contours[member]); + key = str([x,y,w,h]) + '.key' + if not key in dupDict: + dupDict[key] = member + members.append({ 'id' : member, 'bbox' : [x,y,w,h]}) - objectsCandIds.append(members) + objectsCandIds.append(members) - count = hierachy[0][count][0] + count = hierachy[0][count][0] - for family in objectsCandIds: - obj = [] - for member in family: - area = cv2.contourArea(contours[member['id']]) - perimeter = cv2.arcLength(contours[member['id']], True) - pi = 3.14159265359 - Q = 0 - if (area > 10): - Q = 4*pi*area/(perimeter*perimeter) + for family in objectsCandIds: + obj = [] + for member in family: + area = cv2.contourArea(contours[member['id']]) + perimeter = cv2.arcLength(contours[member['id']], True) + pi = 3.14159265359 + Q = 0 + if (area > 10): + Q = 4*pi*area/(perimeter*perimeter) - if Q > 0.7: - diameter = max(member['bbox'][2], member['bbox'][3]) - self.maxDiameter = max(self.maxDiameter, diameter) - self.minDiameter = min(self.minDiameter, diameter) - member['diameter'] = diameter - member['pos'] = (int(member['bbox'][0] + member['bbox'][2]/2), int(member['bbox'][1] + member['bbox'][3]/2)) - obj.append(member) + if Q > 0.7: + diameter = max(member['bbox'][2], member['bbox'][3]) + self.maxDiameter = max(self.maxDiameter, diameter) + self.minDiameter = min(self.minDiameter, diameter) + member['diameter'] = diameter + member['pos'] = (int(member['bbox'][0] + member['bbox'][2]/2), int(member['bbox'][1] + member['bbox'][3]/2)) + obj.append(member) - if obj: - temp_objects.append(obj) + if obj: + temp_objects.append(obj) - for obj in temp_objects: - for member in obj: - if member['diameter'] < self.innerOuterRatio*self.maxDiameter: - member['isHole'] = True - else: - member['isHole'] = False + for obj in temp_objects: + for member in obj: + if member['diameter'] < self.innerOuterRatio*self.maxDiameter: + member['isHole'] = True + else: + member['isHole'] = False - if len(obj) == 2: - self.meanThickness = int(abs(obj[0]['diameter'] - obj[1]['diameter'])/2) + if len(obj) == 2: + self.meanThickness = int(abs(obj[0]['diameter'] - obj[1]['diameter'])/2) - objects.append({'thickness' : self.meanThickness, 'members' : obj}) - + objects.append({'thickness' : self.meanThickness, 'members' : obj}) + except: + pass + return objects def printStats(self): @@ -175,127 +178,128 @@ if args["calibrate"] == 'on': params.append(0) cv2.imwrite("lens_corr.png", np.uint8(lens_corr*127.0), params) + cv2.imwrite("lens_shot.png", frame, params) - sys.exit() - - -frame = np.ones((height, width, 3), np.float32) -lens_corr = np.float32(cv2.imread("lens_corr.png"))/140.0 - -# loop over some frames...this time using the threaded stream -while fps._numFrames < args["num_frames"]: - # grab the frame from the threaded video stream - + fps.stop() if videoFile == "piCamera": - frame = vs.read() - else: - ret, frame = vs.read() + vs.stop() - if args["use_calibration"] == 'on': - frame = np.uint8(cv2.multiply(lens_corr, np.float32(frame))) +else: + frame = np.ones((height, width, 3), np.float32) + lens_corr = np.float32(cv2.imread("lens_corr.png"))/128.0 - kernel = np.ones((3,3),np.uint8) - frame_dilated = cv2.dilate(frame,kernel,iterations = 1) - gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) - gray_blurred = cv2.medianBlur(gray,5) + # loop over some frames...this time using the threaded stream + while fps._numFrames < args["num_frames"]: + # grab the frame from the threaded video stream - # Canny edge detection - img1_canny = cv2.Canny(gray_blurred, 100, 50) - - # Thresholding -# ret,img1_thr = cv2.threshold(gray_blurred,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) -# img1_thr = cv2.adaptiveThreshold(gray_blurred,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,11,2) -# img1_thr = cv2.adaptiveThreshold(gray_blurred,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2) - - # Contours - (_, contours, hierachy) = cv2.findContours(img1_canny.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) - img1_contours = np.zeros((height,width,3), np.uint8) - img1_contours = cv2.drawContours(img1_contours, contours, -1, (0,255,0), 1) - - objects = findObjects.find(contours, hierachy) - -# print (ids) - - img1_objects = frame.copy() - img1_colors = np.zeros((height,width,3), np.uint8) - maskCenter = 4 - roides = [] - beads = [] - for obj in objects: - memberCount = 0 - radius = 0 - roi = 0 - for member in obj['members']: - # Draw bounding box - x,y,w,h = [member['bbox'][0], member['bbox'][1], member['bbox'][2], member['bbox'][3]]; - if member['isHole']: - img1_objects = cv2.rectangle(img1_objects,(x,y),(x+w,y+h),(255,0,0),2) - thickness = obj['thickness']-maskCenter - diameter = member['diameter']+thickness+maskCenter - roi = frame_dilated[y-thickness:y+diameter, x-thickness:x+diameter] - pos = member['pos'] - if diameter > 0: - mask = np.zeros((diameter,diameter,1), np.uint8) - mask = cv2.circle(mask,(int(diameter/2), int(diameter/2)),radius,255,thickness) - mean_color = cv2.mean(roi) - img1_colors = cv2.circle(img1_colors,(int(pos[0]),int(pos[1])),int(diameter/2),mean_color,-1) - beads.append({'pos' : pos, 'diameter' : diameter, 'color' : [mean_color[0]/255, mean_color[1]/255, mean_color[2]/255]}) -# img1_objects = cv2.circle(img1_objects,member['pos'],int(diameter/2),(255,255,255),thickness) - else: - img1_objects = cv2.rectangle(img1_objects,(x,y),(x+w,y+h),(0,0,255),2) - - memberCount += 1 - - for bead in beads: - beadColors.append(bead['color']) - - - colorClasses = [] - for bead in beads: - if not colorClasses: - colorClasses.append(bead['color']) + if videoFile == "piCamera": + frame = vs.read() else: - d, i = mindistance(colorClasses, bead['color']) - if d > 0.14: + ret, frame = vs.read() + + if args["use_calibration"] == 'on': + frame = np.uint8(cv2.multiply(lens_corr, np.float32(frame))) + + kernel = np.ones((3,3),np.uint8) + frame_dilated = cv2.dilate(frame,kernel,iterations = 1) + gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) + gray_blurred = cv2.medianBlur(gray,5) + + # Canny edge detection + img1_canny = cv2.Canny(gray_blurred, 100, 50) + + # Thresholding + # ret,img1_thr = cv2.threshold(gray_blurred,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) + # img1_thr = cv2.adaptiveThreshold(gray_blurred,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,11,2) + # img1_thr = cv2.adaptiveThreshold(gray_blurred,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2) + + # Contours + (_, contours, hierachy) = cv2.findContours(img1_canny.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) + img1_contours = np.zeros((height,width,3), np.uint8) + img1_contours = cv2.drawContours(img1_contours, contours, -1, (0,255,0), 1) + + objects = findObjects.find(contours, hierachy) + + # print (ids) + + img1_objects = frame.copy() + img1_colors = np.zeros((height,width,3), np.uint8) + maskCenter = 4 + roides = [] + beads = [] + for obj in objects: + memberCount = 0 + radius = 0 + roi = 0 + for member in obj['members']: + # Draw bounding box + x,y,w,h = [member['bbox'][0], member['bbox'][1], member['bbox'][2], member['bbox'][3]]; + if member['isHole']: + img1_objects = cv2.rectangle(img1_objects,(x,y),(x+w,y+h),(255,0,0),2) + thickness = obj['thickness']-maskCenter + diameter = member['diameter']+thickness+maskCenter + roi = frame_dilated[y-thickness:y+diameter, x-thickness:x+diameter] + pos = member['pos'] + if diameter > 0: + mask = np.zeros((diameter,diameter,1), np.uint8) + mask = cv2.circle(mask,(int(diameter/2), int(diameter/2)),radius,255,thickness) + mean_color = cv2.mean(roi) + img1_colors = cv2.circle(img1_colors,(int(pos[0]),int(pos[1])),int(diameter/2),mean_color,-1) + beads.append({'pos' : pos, 'diameter' : diameter, 'color' : [mean_color[0]/255, mean_color[1]/255, mean_color[2]/255]}) + # img1_objects = cv2.circle(img1_objects,member['pos'],int(diameter/2),(255,255,255),thickness) + else: + img1_objects = cv2.rectangle(img1_objects,(x,y),(x+w,y+h),(0,0,255),2) + + memberCount += 1 + + for bead in beads: + beadColors.append(bead['color']) + + + colorClasses = [] + for bead in beads: + if not colorClasses: colorClasses.append(bead['color']) else: - colorClasses[i][0] = 0.5*colorClasses[i][0] + 0.5*bead['color'][0] - colorClasses[i][1] = 0.5*colorClasses[i][1] + 0.5*bead['color'][1] - colorClasses[i][2] = 0.5*colorClasses[i][2] + 0.5*bead['color'][2] + d, i = mindistance(colorClasses, bead['color']) + if d > 0.14: + colorClasses.append(bead['color']) + else: + colorClasses[i][0] = 0.5*colorClasses[i][0] + 0.5*bead['color'][0] + colorClasses[i][1] = 0.5*colorClasses[i][1] + 0.5*bead['color'][1] + colorClasses[i][2] = 0.5*colorClasses[i][2] + 0.5*bead['color'][2] - if numColorClasses != len(colorClasses): - numColorClasses = len(colorClasses) - print("Found " + str(numColorClasses) + " color classes") + if numColorClasses != len(colorClasses): + numColorClasses = len(colorClasses) + print("Found " + str(numColorClasses) + " color classes") - cv2.imshow('Corrected', frame) - cv2.imshow('Contours', frame_dilated) - cv2.imshow('Colors', img1_colors) - cv2.imshow('Canny',img1_canny) - cv2.imshow('Objects',img1_objects) - if videoFile == "piCamera": - cv2.waitKey(1) - else: -# cv2.waitKey(0) - cv2.waitKey(int(1000.0/framerate)) + cv2.imshow('Corrected', frame) + cv2.imshow('Contours', frame_dilated) + cv2.imshow('Colors', img1_colors) + cv2.imshow('Canny',img1_canny) + cv2.imshow('Objects',img1_objects) + if videoFile == "piCamera": + cv2.waitKey(1) + else: + # cv2.waitKey(0) + cv2.waitKey(int(1000.0/framerate)) - # update the FPS counter - fps.update() + # update the FPS counter + fps.update() -# stop the timer and display FPS information -fps.stop() -if videoFile == "piCamera": - vs.stop() + # stop the timer and display FPS information + fps.stop() + if videoFile == "piCamera": + vs.stop() -print("[INFO] elasped time: {:.2f}".format(fps.elapsed())) -print("[INFO] approx. FPS: {:.2f}".format(fps.fps())) -if videoFile == "piCamera": - print("[INFO] Camera : elasped time: {:.2f}".format(vs.getfps().elapsed())) - print("[INFO] Camera: approx. FPS: {:.2f}".format(vs.getfps().fps())) + print("[INFO] elasped time: {:.2f}".format(fps.elapsed())) + print("[INFO] approx. FPS: {:.2f}".format(fps.fps())) + if videoFile == "piCamera": + print("[INFO] Camera : elasped time: {:.2f}".format(vs.getfps().elapsed())) + print("[INFO] Camera: approx. FPS: {:.2f}".format(vs.getfps().fps())) -if numColorClasses: - # Output stats findObjects.printStats() @@ -312,16 +316,16 @@ if numColorClasses: red[i] = color[2] plotColors[i] = [red[i], green[i], blue[i]] i += 1 - + # Kmeans create color classes Z = np.float32(plotColors) - + # Define criteria = ( type, max_iter, epsilon ) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.1) - ret,label,center=cv2.kmeans(np.float32(plotColors), numColorClasses, None, criteria, 10, cv2.KMEANS_PP_CENTERS) - + ret,label,center=cv2.kmeans(Z,numColorClasses,None,criteria,10,cv2.KMEANS_PP_CENTERS) + print (center) - + cnt1 = 0 for c1 in center: cnt2 = 0 @@ -338,11 +342,8 @@ if numColorClasses: ax.set_zlabel('red') ax.scatter(blue, green, red, zdir='z', s=10, c=(0,0,0), lw = 0, depthshade=True) ax.scatter(center[:,2], center[:,1], center[:,0], zdir='z', s=500, facecolors=center, lw = 1, depthshade=True) - - plt.show() -else: - print("Sorry, no colors have been detected") + plt.show() # do a bit of cleanup cv2.destroyAllWindows()