41 providerName = getProperty<std::string>(
"providerName").getValue();
42 usingImageProvider(providerName);
44 offeringTopic(getProperty<std::string>(
"OpticalFlowTopicName").getValue());
45 offeringTopic(getProperty<std::string>(
"DebugObserverName").getValue());
47 frameRate = getProperty<float>(
"Framerate").getValue();
49 method = getProperty<OPTICAL_FLOW_METHOD>(
"Method").getValue();
51 chessboardWidth = getProperty<int>(
"Chessboard.Width").getValue();
52 chessboardHeight = getProperty<int>(
"Chessboard.Height").getValue();
54 usingTopic(getProperty<std::string>(
"CalibrationUpdateTopicName").getValue());
59 debugObserver = getTopic<DebugObserverInterfacePrx>(getProperty<std::string>(
"DebugObserverName").getValue());
63 imageDimension = imageProviderInfo.
imageFormat.dimension;
65 imageProviderPrx = getProxy<visionx::ImageProviderInterfacePrx>(providerName);
67 cameraImages =
new CByteImage*[2];
73 prx = getTopic<OpticalFlowListenerPrx>(getProperty<std::string>(
"OpticalFlowTopicName").getValue());
75 enableResultImages(1, imageDimension, visionx::ImageType::eRgb);
78 visionx::StereoCalibrationProviderInterfacePrx calibrationProvider = visionx::StereoCalibrationProviderInterfacePrx::checkedCast(imageProviderPrx);
80 if (calibrationProvider)
82 reportStereoCalibrationChanged(calibrationProvider->getStereoCalibration(),
false,
"");
86 ARMARX_WARNING <<
"unable to obtain calibration parameters. using default values";
88 unitFactorX = (1.0 / 640.0) * (59.7);
89 unitFactorY = (1.0 / 480.0) * (44.775);
105 std::unique_lock lock(imageMutex);
107 if (!waitForImages(getProperty<std::string>(
"providerName").getValue(), 1000))
109 ARMARX_WARNING <<
"Timeout while waiting for camera images (>1000ms)";
113 armarx::MetaInfoSizeBasePtr info;
114 int numImages = getImages(getProperty<std::string>(
"providerName").getValue(), cameraImages, info);
122 IplImage* ppIplImages[1] = { IplImageAdaptor::Adapt(cameraImages[1]) };
126 cv::Mat resultImage = cv::cvarrToMat(ppIplImages[0]);
127 cv::cvtColor(resultImage, grayImage, cv::COLOR_BGR2GRAY);
133 std::vector< cv::Point2f > features;
135 timeDiff = (info->timeProvided - previousTime) / 1000000.0;
137 if ((timeDiff > 1.0) || !previousFeatures.size())
141 ARMARX_INFO <<
"time delta is larger than 1 sec. discarding previous features.";
144 if (!previousFeatures.size())
146 ARMARX_INFO <<
"no feature found on previous image. discarding previous image.";
154 ComputeOpticalFlow(resultImage, grayImage);
162 prx->reportNewOpticalFlow(resultX, resultY, timeDiff, previousTime);
165 debugValues[
"x"] =
new Variant(resultX);
166 debugValues[
"y"] =
new Variant(resultY);
167 debugValues[
"delta_t"] =
new Variant((timeDiff));
170 debugObserver->setDebugChannel(getName(), debugValues);
179 cv::Size size = cv::Size(chessboardWidth, chessboardHeight);
182 bool foundCorners = cv::findChessboardCorners(grayImage, size, features, cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE);
184 cv::drawChessboardCorners(resultImage, size, features, foundCorners);
193 int maxCorners = 100;
194 double qualityLevel = 0.01;
195 double minDistance = 10.0;
198 bool useHarrisDetector =
true;
201 cv::goodFeaturesToTrack(grayImage, features, maxCorners, qualityLevel, minDistance, mask1, blockSize, useHarrisDetector, k);
206 cv::Mat flow = cv::Mat(grayImage.rows, grayImage.cols, CV_32FC1);
207 double mean_flow = 0.;
208 double rmse_flow = 0.;
211 if (previousImage.size() == grayImage.size())
213 cv::calcOpticalFlowFarneback(previousImage, grayImage, flow, 0.5, 10, 45, 3, 9, 1.2, 0);
214 flow = (59.7 / 640.) * flow;
215 flow = (1.0 / timeDiff) * flow;
216 computeAverageDenseFlow(flow, mean_flow, rmse_flow);
221 drawDenseFlowMap(flow, resultImage, 10, CV_RGB(0, 255, 0));
225 debugValues[
"mean_dense"] =
new Variant((mean_flow));
226 debugValues[
"rmse_dense"] =
new Variant((rmse_flow));
227 debugObserver->setDebugChannel(getName(), debugValues);
231 CByteImage* resultImages[1] = { IplImageAdaptor::Adapt(ppIplImages[0]) };
232 provideResultImages(resultImages);
236 if (!features.size())
243 previousImage = grayImage;
244 previousFeatures = features;
245 previousTime = info->timeProvided;
251 fpsCounter.assureFPS(frameRate);
256 void OpticalFlow::ComputeOpticalFlow(cv::Mat resultImage, cv::Mat grayImage)
258 std::vector<uchar>
status;
259 std::vector<float> error;
261 std::vector<cv::Point2f> trackedFeatures;
262 cv::calcOpticalFlowPyrLK(previousImage, grayImage, previousFeatures, trackedFeatures,
status, error, cv::Size(21, 21), cv::OPTFLOW_USE_INITIAL_FLOW);
264 std::vector<float> avgDiffx, avgDiffy;
265 for (
size_t i = 0; i < trackedFeatures.size(); i++)
269 avgDiffx.push_back(previousFeatures[i].x - trackedFeatures[i].x);
270 avgDiffy.push_back(previousFeatures[i].y - trackedFeatures[i].y);
272 cv::circle(resultImage, previousFeatures[i], 2, CV_RGB(255, 0, 0), -1);
273 cv::circle(resultImage, trackedFeatures[i], 2, CV_RGB(0, 0, 255), -1);
274 cv::line(resultImage, previousFeatures[i], trackedFeatures[i], CV_RGB(255, 0, 0), 1);
283 for (
size_t i = 0; i < (avgDiffx.size() / 20); i++)
285 avgDiffx = removeHighestAndLowestMember(avgDiffx);
287 for (
size_t i = 0; i < (avgDiffy.size() / 20); i++)
289 avgDiffy = removeHighestAndLowestMember(avgDiffy);
293 if (!avgDiffx.size() || !avgDiffy.size())
295 ARMARX_WARNING <<
"No features found in the image, return = optical Flow!";
301 Eigen::Map<Eigen::ArrayXf> diffX(avgDiffx.data(), avgDiffx.size());
302 Eigen::Map<Eigen::ArrayXf> diffY(avgDiffy.data(), avgDiffy.size());
305 resultX = diffX.mean() / timeDiff;
306 resultY = diffY.mean() / timeDiff;
308 resultX *= unitFactorX;
309 resultY *= unitFactorY;
312 std::vector<float> OpticalFlow::removeHighestAndLowestMember(std::vector<float>&
input)
318 void OpticalFlow::drawDenseFlowMap(
const cv::Mat& flow, cv::Mat& cflowmap,
int step,
const cv::Scalar& color)
321 for (
int y = 0; y < cflowmap.rows; y += step)
322 for (
int x = 0; x < cflowmap.cols; x += step)
324 const cv::Point2f& fxy = flow.at< cv::Point2f>(y, x);
325 cv::line(cflowmap,
cv::Point(x, y),
cv::Point(cvRound(x + fxy.x), cvRound(y + fxy.y)), color);
326 cv::circle(cflowmap,
cv::Point(cvRound(x + fxy.x), cvRound(y + fxy.y)), 1, color, -1);
331 void OpticalFlow::computeAverageDenseFlow(
const cv::Mat& flow,
double&
mean,
double& rmse)
339 for (
int y = round(flow.rows / 4); y < round(flow.rows * 3 / 4); y ++)
341 for (
int x = round(flow.cols / 4); x < round(flow.cols * 3 / 4); x ++)
343 const cv::Point2f& fxy = flow.at< cv::Point2f>(y, x);
344 d = fxy.x * fxy.x + fxy.y * fxy.y;
351 rmse =
sqrt(dist2 / count);