-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Test Tub Detection (Assuming circular shape) #2
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,4 +46,78 @@ def adjust_volume(self, volume: float) -> str: | |
return None, None | ||
|
||
def check_connection(self) -> bool: | ||
return True | ||
return True | ||
|
||
|
||
import cv2 as cv | ||
import numpy as np | ||
class TestTubeCV: | ||
def __init__(self): | ||
self.videoCapture = cv.VideoCapture(0, cv.CAP_DSHOW) | ||
self.prevCircle = None | ||
self.dist = lambda x1, y1, x2, y2: (x1 - x2) ** 2 + (y1 - y2) ** 2 | ||
self.debug = False | ||
|
||
def predict(self, frame): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using python typing, you can say the following:
This increases code readability so a person looking at this can more easily tell what this function takes in for input and output. You may need to import Tuple and List from typing |
||
""" | ||
Interprets a single frame given to it by the video feed. | ||
Preprocesses the image by first converting it to greyscale, performing a median blur, and then utilizing a Hough Transform to generate circles. | ||
Of the given Hough circles, will filter out any circles that overlap with already predicted circles. | ||
Will get x- and y- corrdinate of each predicted circle's center. | ||
|
||
DISCLAIMER: As of right now, Hough Transform, RANSAC, or some mixture of the two doesn't work the best. | ||
|
||
Args: frame (cv.image): the input image to interpret from and predict on. | ||
Returns: pred (list(int, int)): a list of tuples consisting of the x- and y- coordinates of the predicted circles. | ||
""" | ||
pred = [] | ||
|
||
# blur image for canny detection (Hough Transform) | ||
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) | ||
gray = cv.medianBlur(gray, 13) | ||
|
||
# docstring of HoughCircles: HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles | ||
circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp=1.0, minDist=10, | ||
param1 = 60, | ||
param2 = 75, | ||
minRadius = 1, maxRadius = 50) | ||
if circles is not None: | ||
circles = np.uint16(np.around(circles)) | ||
chosen = None | ||
for i in circles[0, :]: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you explain in comments what's happening here? I think you're comparing the Eucledian distance between chosen and i but not sure what that means or what the algorithm here is... |
||
if chosen is None: | ||
chosen = i | ||
if self.prevCircle is not None: | ||
if self.dist(chosen[0], chosen[1], self.prevCircle[0], self.prevCircle[1]) <= self.dist(i[0], i[1], self.prevCircle[0], self.prevCircle[1]): | ||
chosen = i | ||
cv.circle(frame, (i[0], i[1]), 1, (0, 100, 100), 3) | ||
cv.circle(frame, (i[0], i[1]), i[2], (255, 0 , 255), 3) | ||
|
||
self.prevCircle = chosen | ||
pred.append((chosen[0], chosen[1])) | ||
|
||
|
||
cv.imshow("circles", frame) | ||
cv.imshow("grayscale", gray) | ||
return pred | ||
|
||
def getCircles(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same thing but you can do |
||
""" | ||
Reads in a frame from a birds' eye view video feed, predicts circles, and prints the x- and y- coordinates of the center. | ||
Args: None | ||
Returns: None | ||
""" | ||
while True: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you setup the code such as the if someone calls predict, we can just open the vidoecapture briefly (like one frame) and feed it in. Currently, this code will run forever without letting any of the xArm code to run |
||
ret, frame = self.videoCapture.read() | ||
if not ret: | ||
break | ||
|
||
predicted = self.predict(frame) | ||
if predicted != []: | ||
print(predicted) | ||
|
||
if cv.waitKey(1) == ord('q'): | ||
break | ||
self.videoCapture.release() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I don't think we need this getCircles() method tbh since it'll just be a one off call not a continuous call. I'd just use that for the predict() method. Look at the above comment for more information. |
||
cv.destroyAllWindows() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,18 @@ | ||
#!/usr/bin/env python3 | ||
import os | ||
import sys | ||
|
||
# Add xArm python modules to the PATH | ||
sys.path.append(os.path.join(os.path.dirname(__file__), '..')) | ||
|
||
import time | ||
import json | ||
import argparse | ||
from mypy_types import RequestDict | ||
import logging | ||
from pcr.gizzmos import AtalantaModule | ||
|
||
from xarm.wrapper import XArmAPI | ||
from gizzmos import CustomGripper, PressureSensor | ||
from pcr.gizzmos import CustomGripper, PressureSensor, AtalantaModule | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should probably add TestTubeCV instead of AtalantaModule |
||
|
||
class RunJob(): | ||
SPEED = 50 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add these imports to the top of the file since that's where all of them are. Just good python coding procedure