39 providerName = getProperty<std::string>(
"providerName").getValue();
40 usingImageProvider(providerName);
42 offeringTopic(getProperty<std::string>(
"OpticalFlowTopicName").getValue());
43 offeringTopic(getProperty<std::string>(
"DebugObserverName").getValue());
45 frameRate = getProperty<float>(
"Framerate").getValue();
47 method = getProperty<OPTICAL_FLOW_METHOD>(
"Method").getValue();
49 chessboardWidth = getProperty<int>(
"Chessboard.Width").getValue();
50 chessboardHeight = getProperty<int>(
"Chessboard.Height").getValue();
52 usingTopic(getProperty<std::string>(
"CalibrationUpdateTopicName").getValue());
58 debugObserver = getTopic<DebugObserverInterfacePrx>(
59 getProperty<std::string>(
"DebugObserverName").getValue());
63 imageDimension = imageProviderInfo.
imageFormat.dimension;
65 imageProviderPrx = getProxy<visionx::ImageProviderInterfacePrx>(providerName);
67 cameraImages =
new CByteImage*[2];
72 prx = getTopic<OpticalFlowListenerPrx>(
73 getProperty<std::string>(
"OpticalFlowTopicName").getValue());
75 enableResultImages(1, imageDimension, visionx::ImageType::eRgb);
78 visionx::StereoCalibrationProviderInterfacePrx calibrationProvider =
79 visionx::StereoCalibrationProviderInterfacePrx::checkedCast(imageProviderPrx);
81 if (calibrationProvider)
83 reportStereoCalibrationChanged(calibrationProvider->getStereoCalibration(),
false,
"");
87 ARMARX_WARNING <<
"unable to obtain calibration parameters. using default values";
89 unitFactorX = (1.0 / 640.0) * (59.7);
90 unitFactorY = (1.0 / 480.0) * (44.775);
106 std::unique_lock lock(imageMutex);
108 if (!waitForImages(getProperty<std::string>(
"providerName").getValue(), 1000))
110 ARMARX_WARNING <<
"Timeout while waiting for camera images (>1000ms)";
114 armarx::MetaInfoSizeBasePtr info;
116 getImages(getProperty<std::string>(
"providerName").getValue(), cameraImages, info);
124 IplImage* ppIplImages[1] = {IplImageAdaptor::Adapt(cameraImages[1])};
128 cv::Mat resultImage = cv::cvarrToMat(ppIplImages[0]);
129 cv::cvtColor(resultImage, grayImage, cv::COLOR_BGR2GRAY);
135 std::vector<cv::Point2f> features;
137 timeDiff = (info->timeProvided - previousTime) / 1000000.0;
139 if ((timeDiff > 1.0) || !previousFeatures.size())
143 ARMARX_INFO <<
"time delta is larger than 1 sec. discarding previous features.";
146 if (!previousFeatures.size())
148 ARMARX_INFO <<
"no feature found on previous image. discarding previous image.";
156 ComputeOpticalFlow(resultImage, grayImage);
163 prx->reportNewOpticalFlow(resultX, resultY, timeDiff, previousTime);
166 debugValues[
"x"] =
new Variant(resultX);
167 debugValues[
"y"] =
new Variant(resultY);
168 debugValues[
"delta_t"] =
new Variant((timeDiff));
171 debugObserver->setDebugChannel(getName(), debugValues);
180 cv::Size size = cv::Size(chessboardWidth, chessboardHeight);
183 bool foundCorners = cv::findChessboardCorners(
184 grayImage, size, features, cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE);
186 cv::drawChessboardCorners(resultImage, size, features, foundCorners);
195 int maxCorners = 100;
196 double qualityLevel = 0.01;
197 double minDistance = 10.0;
200 bool useHarrisDetector =
true;
203 cv::goodFeaturesToTrack(grayImage,
216 cv::Mat flow = cv::Mat(grayImage.rows, grayImage.cols, CV_32FC1);
217 double mean_flow = 0.;
218 double rmse_flow = 0.;
221 if (previousImage.size() == grayImage.size())
223 cv::calcOpticalFlowFarneback(
224 previousImage, grayImage, flow, 0.5, 10, 45, 3, 9, 1.2, 0);
225 flow = (59.7 / 640.) * flow;
226 flow = (1.0 / timeDiff) * flow;
227 computeAverageDenseFlow(flow, mean_flow, rmse_flow);
232 drawDenseFlowMap(flow, resultImage, 10, CV_RGB(0, 255, 0));
236 debugValues[
"mean_dense"] =
new Variant((mean_flow));
237 debugValues[
"rmse_dense"] =
new Variant((rmse_flow));
238 debugObserver->setDebugChannel(getName(), debugValues);
242 CByteImage* resultImages[1] = {IplImageAdaptor::Adapt(ppIplImages[0])};
243 provideResultImages(resultImages);
247 if (!features.size())
254 previousImage = grayImage;
255 previousFeatures = features;
256 previousTime = info->timeProvided;
262 fpsCounter.assureFPS(frameRate);
267 OpticalFlow::ComputeOpticalFlow(cv::Mat resultImage, cv::Mat grayImage)
269 std::vector<uchar>
status;
270 std::vector<float> error;
272 std::vector<cv::Point2f> trackedFeatures;
273 cv::calcOpticalFlowPyrLK(previousImage,
280 cv::OPTFLOW_USE_INITIAL_FLOW);
282 std::vector<float> avgDiffx, avgDiffy;
283 for (
size_t i = 0; i < trackedFeatures.size(); i++)
287 avgDiffx.push_back(previousFeatures[i].x - trackedFeatures[i].x);
288 avgDiffy.push_back(previousFeatures[i].y - trackedFeatures[i].y);
290 cv::circle(resultImage, previousFeatures[i], 2, CV_RGB(255, 0, 0), -1);
291 cv::circle(resultImage, trackedFeatures[i], 2, CV_RGB(0, 0, 255), -1);
292 cv::line(resultImage, previousFeatures[i], trackedFeatures[i], CV_RGB(255, 0, 0), 1);
301 for (
size_t i = 0; i < (avgDiffx.size() / 20); i++)
303 avgDiffx = removeHighestAndLowestMember(avgDiffx);
305 for (
size_t i = 0; i < (avgDiffy.size() / 20); i++)
307 avgDiffy = removeHighestAndLowestMember(avgDiffy);
311 if (!avgDiffx.size() || !avgDiffy.size())
313 ARMARX_WARNING <<
"No features found in the image, return = optical Flow!";
319 Eigen::Map<Eigen::ArrayXf> diffX(avgDiffx.data(), avgDiffx.size());
320 Eigen::Map<Eigen::ArrayXf> diffY(avgDiffy.data(), avgDiffy.size());
323 resultX = diffX.mean() / timeDiff;
324 resultY = diffY.mean() / timeDiff;
326 resultX *= unitFactorX;
327 resultY *= unitFactorY;
331 OpticalFlow::removeHighestAndLowestMember(std::vector<float>&
input)
338 OpticalFlow::drawDenseFlowMap(
const cv::Mat& flow,
344 for (
int y = 0; y < cflowmap.rows; y += step)
345 for (
int x = 0; x < cflowmap.cols; x += step)
347 const cv::Point2f& fxy = flow.at<cv::Point2f>(y, x);
350 cv::Point(cvRound(x + fxy.x), cvRound(y + fxy.y)),
352 cv::circle(cflowmap,
cv::Point(cvRound(x + fxy.x), cvRound(y + fxy.y)), 1, color, -1);
358 OpticalFlow::computeAverageDenseFlow(
const cv::Mat& flow,
double&
mean,
double& rmse)
366 for (
int y = round(flow.rows / 4); y < round(flow.rows * 3 / 4); y++)
368 for (
int x = round(flow.cols / 4); x < round(flow.cols * 3 / 4); x++)
370 const cv::Point2f& fxy = flow.at<cv::Point2f>(y, x);
371 d = fxy.x * fxy.x + fxy.y * fxy.y;
378 rmse =
sqrt(dist2 / count);