Skip to content
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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 75 additions & 1 deletion pcr/gizzmos.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

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

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):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using python typing, you can say the following:

def predict(self, frame) -> List[Tuple[[int, int]]]:

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, :]:

Choose a reason for hiding this comment

The 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):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing but you can do def getCircles(self) -> None

"""
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:

Choose a reason for hiding this comment

The 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()

Choose a reason for hiding this comment

The 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()

7 changes: 5 additions & 2 deletions pcr/main.py
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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably add TestTubeCV instead of AtalantaModule


class RunJob():
SPEED = 50
Expand Down