std::vector<cv::Point2f> ShapeFilter::findMassCenter(Data *data){ // check for whether the input is of the correct type. From Albert ImgData* imgData = dynamic_cast<ImgData*>(data); if (imgData == 0) { std::vector<cv::Point2f> bad; return bad; } return findMassCenter(imgData->getImg()); }
bool ShapeFilter::filter(Data *data){ // check for whether the input is of the correct type. From Albert ImgData* imgData = dynamic_cast<ImgData*>(data); if (imgData == 0) { // track the error and return error this->track(data,this->filterID,1,1); return false; } //beging filtering process if (shape == 1){ ///rectangle return this->findRect((imgData->getImg())); //lazy to copy+paste everything }else if (shape == 2){ ///circle return this->findCirc(imgData->getImg()); } //ending filtering process //track and return this->track(imgData, this->filterID, 0,0); return true; }
bool LineFilter::filter(Data *data){ // check for whether the input is of the correct type. From Albert ImgData* imgData = dynamic_cast<ImgData*>(data); if (imgData == 0) { // track the error and return error this->track(data,this->filterID,1,1); return false; } cv::imshow("asdf", filter(imgData->getImg().clone(),0)); //begin filter sequence int linesFound = 0; cv::Mat src = imgData->getImg(); cv::Mat dst; cv::Mat cdst = src.clone(); Canny(src, dst, 50, 200, 3); cvtColor(dst, cdst, CV_GRAY2BGR); std::vector<cv::Vec2f> lines; //detects lines HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 ); //ending filter sequence //calculating the line equation linesEq.clear(); float x1 = 0, x2 = 0, y1 = 0, y2 = 0; for( size_t i = 0; i < lines.size(); i++ ){ float rho = lines[i][0], theta = lines[i][1]; cv::Point pt1, pt2; double a = cos(theta), b = sin(theta); double x0 = a*rho, y0 = b*rho; pt1.x = cvRound(x0 + 1000*(-b)); pt1.y = cvRound(y0 + 1000*(a)); pt2.x = cvRound(x0 - 1000*(-b)); pt2.y = cvRound(y0 - 1000*(a)); x1 = pt1.x; y1 = pt1.y; x2 = pt2.x; y2 = pt2.y; //equation of line std::vector<float> eq; //y = mx+b //B MIGHT BE USELSES, NEED FURTHER TESTING bool safeMath = true; float M = 0, B = 0; if (x2-x1 < 5){ //straight line safeMath = false; M = INFINITY; B = INFINITY; } if (safeMath){ //avoid div by 0 error //M = (y2-y1) / (x2-x1); double realtheta = (rho < 0)? theta - M_PI:theta; realtheta = -realtheta + M_PI/2; M = tan(realtheta); B = y2 - M*x2; } bool repeat = false; //check if there is a similar line already for (std::vector<float> lines: linesEq){ //vert line situations if (M == INFINITY && lines[0] == INFINITY){ //check their x values if (std::abs(lines[2] - ((x1+x2)/2)) < maxDiff){ repeat = true; break; } } //check if m is almost vertical else if (std::abs(M) > maxSlope && lines[0] == INFINITY){ //std::cout<<"almost vert "; //std::cout<<std::abs(lines[2] - ((x1+x2)/2))<<std::endl; if (std::abs(lines[2] - ((x1+x2)/2) ) < maxDiff){ repeat = true; break; } } else if (M == INFINITY && std::abs(lines[0])> maxSlope){ //std::cout<<"almost vert II "; //std::cout<<std::abs(lines[2] - ((x1+x2)/2))<<std::endl; if (std::abs(lines[2] - ((x1+x2)/2) ) < maxDiff){ repeat = true; break; } } //check if m is too similar or not, b is too different to check else if (std::abs(lines[0] - M) < maxDiff){ if (M > 15){ //vertical lines //check if the intersection point is near the average x if (std::abs((B-lines[1])/(lines[0]-M))-(x1+x2)/2 < maxDiff){ repeat = true; break; } }else{ //horziontal lines if (std::abs((B-lines[1])/(lines[0]-M))*M - (y1+y2)/2 < maxDiff){ repeat = true; break; } } } } if (!repeat){ eq.push_back(M); eq.push_back(B); //std::cout<<M<<" "<<B<<" " << ((x1+x2)/2) << " "; if (std::abs(M) < 5){ //aprox horizontal line eq.push_back(y2); //give it the y value //std::cout<<y2; //printf(" horz line"); } if (std::abs(M) > maxSlope){ //vertical line eq.push_back(x2); //x value //std::cout<<x2; //printf(" vertal line"); } //std::cout<<std::endl; linesEq.push_back(eq); linesFound++; //line(*cdst, pt1, pt2, cv::Scalar(0,0,255), 3, CV_AA); //drawing the line } } //should i set imgData to something?? -Carl //track and return this->track(imgData, this->filterID, 0,0); //println(linesFound != 0); return linesFound != 0; }
void BuoyTask::execute() { HSVFilter green(std::stoi(settings->getProperty("g1")), std::stoi(settings->getProperty("g2")), std::stoi(settings->getProperty("g3")), std::stoi(settings->getProperty("g4")), std::stoi(settings->getProperty("g5")), std::stoi(settings->getProperty("g6"))); HSVFilter red(std::stoi(settings->getProperty("r1")), std::stoi(settings->getProperty("r2")), std::stoi(settings->getProperty("r3")), std::stoi(settings->getProperty("r4")), std::stoi(settings->getProperty("r5")), std::stoi(settings->getProperty("r6"))); //only look for 1 circle ShapeFilter sf (2, 1); //assuming the sub is in the correct position //first look for red, and then hit it //then look and hit green bool hitGreen = false; bool hitRed = false; int retreat = 0; int moveDist = std::stoi(settings->getProperty("moveDist")); int rotateAng = std::stoi(settings->getProperty("rotateAng")); int movementDelay = std::stoi(settings->getProperty("movementDelay")); int deltaDist = 0; float deltaT = 0; bool done = false; while (!done) { std::string s = "raw"; ImgData* data = dynamic_cast<ImgData*> (dynamic_cast<CameraState*> (camModel->getState())->getDeepState(s)); imgWidth = data->getImg().size().width; imgHeight = data->getImg().size().height; // cv::imshow("hsv",data->getImg()); //filter for a color depending if the other color is hit or not if (!hitRed){ println("Filtering red"); red.filter(data); } else if (!hitGreen){ //println("Filtering green"); //green.filter(data); done = true; continue; } else if (hitGreen && hitRed) { done = true; println("Done task"); continue; } //after hitting a color, move the sub back to look for the other one //TODO: CALIBRATE THIS STEP if (sf.filter(data)){ retreat = false; cv::Point2f cent = sf.getCenter()[0]; if (std::abs(cent.x - imgWidth/2) < imgWidth/20){ //in the middle 20% of the screen horizontally if (std::abs(cent.y - imgHeight / 2) < imgHeight / 20) { //in the middle 20% vertically float d = calcDistance(sf.getRad()[0]) * 1.2; float t = d/moveSpeed; println("Moving " + std::to_string(d) + "cm in " + std::to_string(t) + "s"); move(moveSpeed); usleep(std::stoi(settings->getProperty("MOVE_TIME"))); if (!hitRed){ hitRed = true; println("Hit red"); retreat = true; } else { hitGreen = true; println("Hit green"); retreat = true; } logger->info("Stopping"); move(0); /* //if the radius of the circle is huge, so the sub will hit it if (sf.getRad()[0] > imgWidth*imgHeight/3){ if (!hitGreen){ hitGreen = true; println("Hit green"); }else{ hitRed = true; println("Hit red"); } //return the sub back to its orginal position move(0); retreat = true; println("Retreat enabled"); }else{ //move straight and hit it float dist = calcDistance(sf.getRad()[0]); deltaDist = dist*1.2; println("Moving forward " + std::to_string(deltaDist) + "cm to hit buoy"); move(deltaDist); }*/ } else { float deltaY; if (cent.y > imgHeight/2) { deltaY = -0.1; //rise a bit } else { deltaY = 0.1; //sink a bit } //float deltaY = (cent.y - imgHeight/2)/sf.getRad()[0]; println("Rising " + std::to_string(deltaY*100)+"cm"); changeDepth(deltaY); } } else { println("Center: " + std::to_string(cent.x) + " " + std::to_string(imgWidth/2)); //float ang = atan2(cent.x-imgWidth/2, 0) * 180 / M_PI; //float dX = cent.x-imgWidth/2; //dX * 23/sf.getRad()[0]; //float ang = atan(dX/calcDistance(sf.getRad()[0])) * 180 / M_PI; //println("Rotating " + std::to_string(ang) + " degrees"); //rotate(ang); float dir = cent.x-imgWidth/2; println("Rotating 10 degrees " + std::to_string(dir)); dir /= std::abs(dir); rotate (5*dir); /* float scale = 23/sf.getRad()[0]; float dist = sf.getCenter()[0].x - imgWidth/2; //slide 2/3 of the way float deltaX = dist*scale/3*2; println("Sliding " + std::to_string(deltaX)+"cm"); slide(deltaX);*/ } } else { ///CIRCLES NOT FOUND ///ROTATE/MOVE SUB //rotate(rotateAng); println("Circle not found, moving forward"); //move(moveDist); if (retreat) { if (moveWithSpeed){ println("Retreating"); move(-moveSpeed); usleep(40000000); //usleep(deltaT * 500); move(0); rotate(-deltaAngle); usleep(5000000); } else { println("Retreating " + std::to_string(-deltaDist - 20) + "cm"); move(-deltaDist - 20); //move 20cm more than i needed //sleep(movementDelay); //move the sub back to the middle if (deltaAngle != -1){ println("Retreat rotating " + std::to_string(deltaAngle) + " degrees"); rotate(deltaAngle); println("Retreat to middle by " + std::to_string(deltaDist-20) + "cm"); move (deltaDist-20); //move 20cm less than i need rotate(-deltaAngle); } } retreat = false; // continue; } else { ///tries to look for any colors and move towards it logger->info("Looking for coloured masses to turn towards"); std::vector<cv::Point2f> mc = sf.findMassCenter(data); if (mc.size() > 0) { logger->info("Found coloured mass"); float dir = mc[0].x - imgWidth/2; dir /= std::abs(dir); rotate(5 * dir); } else { ///if it dosnt see any colors, move forwards logger->debug("No coloured masses found. Moving forward"); move(moveSpeed); } } } delete data; data = 0; usleep(33000); } }
bool RGBFilter::filter(Data* data) { // check for whether the input is of the correct type. ImgData* cast = dynamic_cast<ImgData*>(data); if (cast == 0) { // track the error and return error this->track(data,this->filterID,1,1); return false; } if (cast->img.type() != 16) { this->track(data,this->filterID,2,1); return false; } // begin filter sequence. int newPixelVal; cv::Mat src = cast->getImg(); cv::Mat filteredImg = src.clone(); cv::Mat BGR[3]; cv::split(filteredImg,BGR); // catch error? // Full spectrum mode if(this->mode == 0) { for(int y = 0; y < src.cols; y++ ) { for(int x = 0; x < src.rows; x++ ) { for(int c = 0; c < 3; c++) { newPixelVal = std::max(0,std::min(mxColour,BGR[c].at<unsigned char>(x,y) + midMult[c]*midtone[c])); BGR[c].at<unsigned char>(x,y) = newPixelVal; } } } } // 3 zone mode if (this->mode == 1) { int luminosity; const int SHADTHRESHOLD = (int) mxColour*10/3; const int HIGHTHRESHOLD = SHADTHRESHOLD * 2; // get luminosity with some function // use luminosity as a switch for case using high, mid or shad for(int y = 0; y < src.cols; y++ ) { for(int x = 0; x < src.rows; x++ ) { // From 11%,59%,30% bgr respectively. Scaled to 1:6:3 factors // luminosity range is from 0-2550, 1/3 is 850. Calc this from: // 10*255, 10* MXCOLOR luminosity = BGR[0].at<unsigned char>(x,y)*1+BGR[1].at<unsigned char>(x,y)*6+BGR[2].at<unsigned char>(x,y)*3; for(int c = 0; c < 3; c++) { if (luminosity < SHADTHRESHOLD) newPixelVal = std::max(0,std::min(mxColour,BGR[c].at<unsigned char>(x,y) + shadMult[c]*shadow[c])); else if (luminosity > HIGHTHRESHOLD) newPixelVal = std::max(0,std::min(mxColour,BGR[c].at<unsigned char>(x,y) + highMult[c]*highlight[c])); else newPixelVal = std::max(0,std::min(mxColour,BGR[c].at<unsigned char>(x,y) + midMult[c]*midtone[c])); BGR[c].at<unsigned char>(x,y) = newPixelVal; } } } } //joining seq cv::merge(BGR,3,filteredImg); //set sequence cast->setImg(filteredImg); // end sequence. // track and return this->track(cast,this->filterID,0,0); return true; }