vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(live_demo)
|
||||
find_package(OpenCV 3.0 REQUIRED)
|
||||
|
||||
set(SOURCES live_demo.cpp)
|
||||
|
||||
include_directories(${OpenCV_INCLUDE_DIRS})
|
||||
add_executable(live_demo ${SOURCES} ${HEADERS})
|
||||
target_link_libraries(live_demo ${OpenCV_LIBS})
|
||||
@@ -0,0 +1,106 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2017, IBM Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Marc Fiammante marc.fiammante@fr.ibm.com
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of OpenCV Foundation or contributors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the OpenCV Foundation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
#include "opencv2/core/utility.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "opencv2/ximgproc.hpp"
|
||||
using namespace cv;
|
||||
using namespace ximgproc;
|
||||
using namespace std;
|
||||
|
||||
static void help()
|
||||
{
|
||||
printf("\nThis sample demonstrates BrightEdge detection\n"
|
||||
"Call:\n"
|
||||
" /.edge [image_name -- Default is ../data/ml.png]\n\n");
|
||||
}
|
||||
const char* keys =
|
||||
{
|
||||
"{help h||}{@image |../data/ml.png|input image name}"
|
||||
};
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
CommandLineParser parser(argc, argv, keys);
|
||||
if (parser.has("help"))
|
||||
{
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
string filename = parser.get<string>(0);
|
||||
Mat image = imread(filename, IMREAD_COLOR);
|
||||
if (image.empty())
|
||||
{
|
||||
printf("Cannot read image file: %s\n", filename.c_str());
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
// Create a window
|
||||
// // " original ";
|
||||
namedWindow("Original");
|
||||
imshow("Original", image);
|
||||
// " absdiff ";
|
||||
Mat edge;
|
||||
BrightEdges(image, edge, 0); // No contrast
|
||||
namedWindow("Absolute Difference");
|
||||
imshow("Absolute Difference", edge);
|
||||
// " default contrast 1 ";
|
||||
BrightEdges(image, edge);
|
||||
namedWindow("Default contrast");
|
||||
imshow("Default contrast", edge);// Default contrast 1
|
||||
// " Contrast 5 \n";
|
||||
BrightEdges(image, edge, 5);
|
||||
namedWindow("Contrast 5");
|
||||
imshow("Contrast 5", edge);
|
||||
// " Contrast 10 \n";
|
||||
BrightEdges(image, edge, 10);
|
||||
namedWindow("Contrast 10");
|
||||
imshow("Contrast 10", edge);
|
||||
// "wait key ";
|
||||
waitKey(0);
|
||||
// "end ";
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
#include <opencv2/ximgproc/color_match.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
|
||||
|
||||
static void AddSlider(String sliderName, String windowName, int minSlider, int maxSlider, int valDefault, int *valSlider, void(*f)(int, void *), void *r)
|
||||
{
|
||||
createTrackbar(sliderName, windowName, valSlider, 1, f, r);
|
||||
setTrackbarMin(sliderName, windowName, minSlider);
|
||||
setTrackbarMax(sliderName, windowName, maxSlider);
|
||||
setTrackbarPos(sliderName, windowName, valDefault);
|
||||
}
|
||||
|
||||
struct SliderData {
|
||||
Mat img;
|
||||
int thresh;
|
||||
};
|
||||
|
||||
static void UpdateThreshImage(int , void *r)
|
||||
{
|
||||
SliderData *p = (SliderData*)r;
|
||||
Mat dst,labels,stats,centroids;
|
||||
|
||||
threshold(p->img, dst, p->thresh, 255, THRESH_BINARY);
|
||||
|
||||
connectedComponentsWithStats(dst, labels, stats, centroids, 8);
|
||||
if (centroids.rows < 10)
|
||||
{
|
||||
cout << "**********************************************************************************\n";
|
||||
for (int i = 0; i < centroids.rows; i++)
|
||||
{
|
||||
cout << dst.cols - centroids.at<double>(i, 0) << " ";
|
||||
cout << dst.rows - centroids.at<double>(i, 1) << "\n";
|
||||
}
|
||||
cout << "----------------------------------------------------------------------------------\n";
|
||||
}
|
||||
flip(dst, dst, -1);
|
||||
|
||||
imshow("Max Quaternion corr",dst);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
cv::CommandLineParser parser(argc, argv,
|
||||
"{help h | | match color image }{@colortemplate | | input color template image}{@colorimage | | input color image}");
|
||||
if (parser.has("help"))
|
||||
{
|
||||
parser.printMessage();
|
||||
return -1;
|
||||
}
|
||||
string templateName = parser.get<string>("@colortemplate");
|
||||
if (templateName.empty())
|
||||
{
|
||||
parser.printMessage();
|
||||
parser.printErrors();
|
||||
return -2;
|
||||
}
|
||||
string colorImageName = parser.get<string>("@colorimage");
|
||||
if (templateName.empty())
|
||||
{
|
||||
parser.printMessage();
|
||||
parser.printErrors();
|
||||
return -2;
|
||||
}
|
||||
Mat imgLogo = imread(templateName, IMREAD_COLOR);
|
||||
Mat imgColor = imread(colorImageName, IMREAD_COLOR);
|
||||
imshow("Image", imgColor);
|
||||
imshow("template", imgLogo);
|
||||
// OK NOW WHERE IS OPENCV LOGO ?
|
||||
Mat imgcorr;
|
||||
SliderData ps;
|
||||
ximgproc::colorMatchTemplate(imgColor, imgLogo, imgcorr);
|
||||
imshow("quaternion correlation real", imgcorr);
|
||||
normalize(imgcorr, imgcorr,1,0,NORM_MINMAX);
|
||||
imgcorr.convertTo(ps.img, CV_8U, 255);
|
||||
imshow("quaternion correlation", imgcorr);
|
||||
ps.thresh = 0;
|
||||
AddSlider("Level", "quaternion correlation", 0, 255, ps.thresh, &ps.thresh, UpdateThreshImage, &ps);
|
||||
int code = 0;
|
||||
while (code != 27)
|
||||
{
|
||||
code = waitKey(50);
|
||||
}
|
||||
|
||||
waitKey(0);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/core/utility.hpp"
|
||||
|
||||
#include <time.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
|
||||
|
||||
|
||||
using namespace cv;
|
||||
|
||||
#ifdef HAVE_EIGEN
|
||||
|
||||
#define MARK_RADIUS 5
|
||||
#define PALLET_RADIUS 100
|
||||
int max_width = 1280;
|
||||
int max_height = 720;
|
||||
|
||||
static int globalMouseX;
|
||||
static int globalMouseY;
|
||||
static int selected_r;
|
||||
static int selected_g;
|
||||
static int selected_b;
|
||||
static bool globalMouseClick = false;
|
||||
static bool glb_mouse_left = false;
|
||||
static bool drawByReference = false;
|
||||
static bool mouseDraw = false;
|
||||
static bool mouseClick;
|
||||
static bool mouseLeft;
|
||||
static int mouseX;
|
||||
static int mouseY;
|
||||
|
||||
cv::Mat mat_draw;
|
||||
cv::Mat mat_input_gray;
|
||||
cv::Mat mat_input_reference;
|
||||
cv::Mat mat_input_confidence;
|
||||
cv::Mat mat_pallet(PALLET_RADIUS*2,PALLET_RADIUS*2,CV_8UC3);
|
||||
|
||||
|
||||
static void mouseCallback(int event, int x, int y, int flags, void* param);
|
||||
void drawTrajectoryByReference(cv::Mat& img);
|
||||
double module(Point pt);
|
||||
double distance(Point pt1, Point pt2);
|
||||
double cross(Point pt1, Point pt2);
|
||||
double angle(Point pt1, Point pt2);
|
||||
int inCircle(Point p, Point c, int r);
|
||||
void createPlate(Mat &im1, int radius);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
const String keys =
|
||||
"{help h usage ? | | print this message }"
|
||||
"{@image | | input image }"
|
||||
"{sigma_spatial |8 | parameter of post-filtering }"
|
||||
"{sigma_luma |8 | parameter of post-filtering }"
|
||||
"{sigma_chroma |8 | parameter of post-filtering }"
|
||||
"{dst_path |None | optional path to save the resulting colorized image }"
|
||||
"{dst_raw_path |None | optional path to save drawed image before filtering }"
|
||||
"{draw_by_reference |false | optional flag to use color image as reference }"
|
||||
;
|
||||
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
CommandLineParser parser(argc,argv,keys);
|
||||
parser.about("fastBilateralSolverFilter Demo");
|
||||
if (parser.has("help"))
|
||||
{
|
||||
parser.printMessage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EIGEN
|
||||
|
||||
String img = parser.get<String>(0);
|
||||
double sigma_spatial = parser.get<double>("sigma_spatial");
|
||||
double sigma_luma = parser.get<double>("sigma_luma");
|
||||
double sigma_chroma = parser.get<double>("sigma_chroma");
|
||||
String dst_path = parser.get<String>("dst_path");
|
||||
String dst_raw_path = parser.get<String>("dst_raw_path");
|
||||
drawByReference = parser.get<bool>("draw_by_reference");
|
||||
|
||||
mat_input_reference = cv::imread(img, IMREAD_COLOR);
|
||||
if (mat_input_reference.empty())
|
||||
{
|
||||
std::cerr << "input image '" << img << "' could not be read !" << std::endl << std::endl;
|
||||
parser.printMessage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
cvtColor(mat_input_reference, mat_input_gray, COLOR_BGR2GRAY);
|
||||
|
||||
if(mat_input_gray.cols > max_width)
|
||||
{
|
||||
double scale = float(max_width) / float(mat_input_gray.cols);
|
||||
cv::resize(mat_input_reference, mat_input_reference, cv::Size(), scale, scale);
|
||||
cv::resize(mat_input_gray, mat_input_gray, cv::Size(), scale, scale);
|
||||
}
|
||||
|
||||
if(mat_input_gray.rows > max_height)
|
||||
{
|
||||
double scale = float(max_height) / float(mat_input_gray.rows);
|
||||
cv::resize(mat_input_reference, mat_input_reference, cv::Size(), scale, scale);
|
||||
cv::resize(mat_input_gray, mat_input_gray, cv::Size(), scale, scale);
|
||||
}
|
||||
|
||||
|
||||
float filtering_time;
|
||||
std::cout << "mat_input_reference:" << mat_input_reference.cols<<"x"<< mat_input_reference.rows<< std::endl;
|
||||
std::cout << "please select a color from the palette, by clicking into that," << std::endl;
|
||||
std::cout << " then select a coarse region in the image to be coloured." << std::endl;
|
||||
std::cout << " press 'escape' to see the final coloured image." << std::endl;
|
||||
|
||||
|
||||
cv::Mat mat_gray;
|
||||
cv::cvtColor(mat_input_reference, mat_gray, cv::COLOR_BGR2GRAY);
|
||||
|
||||
cv::Mat target = mat_input_reference.clone();
|
||||
cvtColor(mat_gray, mat_input_reference, COLOR_GRAY2BGR);
|
||||
|
||||
cv::namedWindow("draw", cv::WINDOW_AUTOSIZE);
|
||||
|
||||
// construct pallet
|
||||
createPlate(mat_pallet, PALLET_RADIUS);
|
||||
selected_b = 0;
|
||||
selected_g = 0;
|
||||
selected_r = 0;
|
||||
|
||||
cv::Mat mat_show(target.rows,target.cols+PALLET_RADIUS*2,CV_8UC3);
|
||||
cv::Mat color_select(target.rows-mat_pallet.rows,PALLET_RADIUS*2,CV_8UC3,cv::Scalar(selected_b, selected_g, selected_r));
|
||||
target.copyTo(Mat(mat_show,Rect(0,0,target.cols,target.rows)));
|
||||
mat_pallet.copyTo(Mat(mat_show,Rect(target.cols,0,mat_pallet.cols,mat_pallet.rows)));
|
||||
color_select.copyTo(Mat(mat_show,Rect(target.cols,PALLET_RADIUS*2,color_select.cols,color_select.rows)));
|
||||
|
||||
cv::imshow("draw", mat_show);
|
||||
cv::setMouseCallback("draw", mouseCallback, (void *)&mat_show);
|
||||
mat_input_confidence = 0*cv::Mat::ones(mat_gray.size(),mat_gray.type());
|
||||
|
||||
int show_count = 0;
|
||||
while (1)
|
||||
{
|
||||
mouseX = globalMouseX;
|
||||
mouseY = globalMouseY;
|
||||
mouseClick = globalMouseClick;
|
||||
mouseLeft = glb_mouse_left;
|
||||
|
||||
|
||||
if (mouseClick)
|
||||
{
|
||||
drawTrajectoryByReference(target);
|
||||
|
||||
if(show_count%5==0)
|
||||
{
|
||||
cv::Mat target_temp(target.size(),target.type());
|
||||
filtering_time = static_cast<float>(getTickCount());
|
||||
if(mouseDraw)
|
||||
{
|
||||
cv::cvtColor(target, target_temp, cv::COLOR_BGR2YCrCb);
|
||||
std::vector<cv::Mat> src_channels;
|
||||
std::vector<cv::Mat> dst_channels;
|
||||
|
||||
cv::split(target_temp,src_channels);
|
||||
|
||||
cv::Mat result1 = cv::Mat(mat_input_gray.size(),mat_input_gray.type());
|
||||
cv::Mat result2 = cv::Mat(mat_input_gray.size(),mat_input_gray.type());
|
||||
|
||||
dst_channels.push_back(mat_input_gray);
|
||||
cv::ximgproc::fastBilateralSolverFilter(mat_input_gray,src_channels[1],mat_input_confidence,result1,sigma_spatial,sigma_luma,sigma_chroma);
|
||||
dst_channels.push_back(result1);
|
||||
cv::ximgproc::fastBilateralSolverFilter(mat_input_gray,src_channels[2],mat_input_confidence,result2,sigma_spatial,sigma_luma,sigma_chroma);
|
||||
dst_channels.push_back(result2);
|
||||
|
||||
cv::merge(dst_channels,target_temp);
|
||||
cv::cvtColor(target_temp, target_temp, cv::COLOR_YCrCb2BGR);
|
||||
}
|
||||
else
|
||||
{
|
||||
target_temp = target.clone();
|
||||
}
|
||||
filtering_time = static_cast<float>(((double)getTickCount() - filtering_time)/getTickFrequency());
|
||||
std::cout << "solver time: " << filtering_time << "s" << std::endl;
|
||||
|
||||
cv::Mat color_selected(target_temp.rows-mat_pallet.rows,PALLET_RADIUS*2,CV_8UC3,cv::Scalar(selected_b, selected_g, selected_r));
|
||||
target_temp.copyTo(Mat(mat_show,Rect(0,0,target_temp.cols,target_temp.rows)));
|
||||
mat_pallet.copyTo(Mat(mat_show,Rect(target_temp.cols,0,mat_pallet.cols,mat_pallet.rows)));
|
||||
color_selected.copyTo(Mat(mat_show,Rect(target_temp.cols,PALLET_RADIUS*2,color_selected.cols,color_selected.rows)));
|
||||
cv::imshow("draw", mat_show);
|
||||
}
|
||||
show_count++;
|
||||
}
|
||||
if (cv::waitKey(2) == 27)
|
||||
break;
|
||||
}
|
||||
mat_draw = target.clone();
|
||||
cv::cvtColor(target, target, cv::COLOR_BGR2YCrCb);
|
||||
|
||||
std::vector<cv::Mat> src_channels;
|
||||
std::vector<cv::Mat> dst_channels;
|
||||
|
||||
cv::split(target,src_channels);
|
||||
|
||||
cv::Mat result1 = cv::Mat(mat_input_gray.size(),mat_input_gray.type());
|
||||
cv::Mat result2 = cv::Mat(mat_input_gray.size(),mat_input_gray.type());
|
||||
|
||||
filtering_time = static_cast<float>(getTickCount());
|
||||
|
||||
// dst_channels.push_back(src_channels[0]);
|
||||
dst_channels.push_back(mat_input_gray);
|
||||
cv::ximgproc::fastBilateralSolverFilter(mat_input_gray,src_channels[1],mat_input_confidence,result1,sigma_spatial,sigma_luma,sigma_chroma);
|
||||
dst_channels.push_back(result1);
|
||||
cv::ximgproc::fastBilateralSolverFilter(mat_input_gray,src_channels[2],mat_input_confidence,result2,sigma_spatial,sigma_luma,sigma_chroma);
|
||||
dst_channels.push_back(result2);
|
||||
|
||||
cv::merge(dst_channels,target);
|
||||
cv::cvtColor(target, target, cv::COLOR_YCrCb2BGR);
|
||||
|
||||
filtering_time = static_cast<float>(((double)getTickCount() - filtering_time)/getTickFrequency());
|
||||
std::cout << "solver time: " << filtering_time << "s" << std::endl;
|
||||
|
||||
|
||||
|
||||
cv::imshow("mat_draw",mat_draw);
|
||||
cv::imshow("output",target);
|
||||
|
||||
if(dst_path!="None")
|
||||
{
|
||||
imwrite(dst_path,target);
|
||||
}
|
||||
if(dst_raw_path!="None")
|
||||
{
|
||||
imwrite(dst_raw_path,mat_draw);
|
||||
}
|
||||
|
||||
cv::waitKey(0);
|
||||
|
||||
|
||||
|
||||
#else
|
||||
std::cout << "Can not find eigen, please build with eigen by set WITH_EIGEN=ON" << '\n';
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_EIGEN
|
||||
static void mouseCallback(int event, int x, int y, int, void*)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case cv::EVENT_MOUSEMOVE:
|
||||
if (globalMouseClick)
|
||||
{
|
||||
globalMouseX = x;
|
||||
globalMouseY = y;
|
||||
}
|
||||
break;
|
||||
|
||||
case cv::EVENT_LBUTTONDOWN:
|
||||
globalMouseClick = true;
|
||||
globalMouseX = x;
|
||||
globalMouseY = y;
|
||||
break;
|
||||
|
||||
case cv::EVENT_LBUTTONUP:
|
||||
glb_mouse_left = true;
|
||||
globalMouseClick = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void drawTrajectoryByReference(cv::Mat& img)
|
||||
{
|
||||
int i, j;
|
||||
uchar red, green, blue;
|
||||
float gray;
|
||||
int y, x;
|
||||
int r = MARK_RADIUS;
|
||||
int r2 = r * r;
|
||||
uchar* colorPix;
|
||||
uchar* grayPix;
|
||||
|
||||
if(mouseY < PALLET_RADIUS*2 && img.cols <= mouseX && mouseX < img.cols+PALLET_RADIUS*2)
|
||||
{
|
||||
colorPix = mat_pallet.ptr<uchar>(mouseY, mouseX - img.cols);
|
||||
// colorPix = mat_pallet.ptr<uchar>(mouseY, mouseX);
|
||||
selected_b = *colorPix;
|
||||
colorPix++;
|
||||
selected_g = *colorPix;
|
||||
colorPix++;
|
||||
selected_r = *colorPix;
|
||||
colorPix++;
|
||||
std::cout << "x y:("<<mouseX<<"," <<mouseY<< " rgb_select:("<< selected_r<<","<<selected_g<<","<<selected_b<<")" << '\n';
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseDraw = true;
|
||||
y = mouseY - r;
|
||||
for(i=-r; i<r+1 ; i++, y++)
|
||||
{
|
||||
x = mouseX - r;
|
||||
colorPix = mat_input_reference.ptr<uchar>(y, x);
|
||||
grayPix = mat_input_gray.ptr<uchar>(y, x);
|
||||
for(j=-r; j<r+1; j++, x++)
|
||||
{
|
||||
if(i*i + j*j > r2)
|
||||
{
|
||||
colorPix += mat_input_reference.channels();
|
||||
grayPix += mat_input_gray.channels();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(y<0 || y>=mat_input_reference.rows || x<0 || x>=mat_input_reference.cols)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
blue = *colorPix;
|
||||
colorPix++;
|
||||
green = *colorPix;
|
||||
colorPix++;
|
||||
red = *colorPix;
|
||||
colorPix++;
|
||||
gray = *grayPix;
|
||||
grayPix++;
|
||||
mat_input_confidence.at<uchar>(y,x) = 255;
|
||||
float draw_y = 0.229f*(float(selected_r)) + 0.587f*(float(selected_g)) + 0.114f*(float(selected_b));
|
||||
int draw_b = int(float(selected_b)*(gray/draw_y));
|
||||
int draw_g = int(float(selected_g)*(gray/draw_y));
|
||||
int draw_r = int(float(selected_r)*(gray/draw_y));
|
||||
|
||||
if(drawByReference)
|
||||
{
|
||||
cv::circle(img, cv::Point2d(x, y), 1, cv::Scalar(blue, green, red), -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::circle(img, cv::Point2d(x, y), 1, cv::Scalar(draw_b, draw_g, draw_r), -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double module(Point pt)
|
||||
{
|
||||
return sqrt((double)pt.x*pt.x + pt.y*pt.y);
|
||||
}
|
||||
|
||||
double distance(Point pt1, Point pt2)
|
||||
{
|
||||
int dx = pt1.x - pt2.x;
|
||||
int dy = pt1.y - pt2.y;
|
||||
return sqrt((double)dx*dx + dy*dy);
|
||||
}
|
||||
|
||||
double cross(Point pt1, Point pt2)
|
||||
{
|
||||
return pt1.x*pt2.x + pt1.y*pt2.y;
|
||||
}
|
||||
|
||||
double angle(Point pt1, Point pt2)
|
||||
{
|
||||
return acos(cross(pt1, pt2) / (module(pt1)*module(pt2) + DBL_EPSILON));
|
||||
}
|
||||
|
||||
// p or c is the center
|
||||
int inCircle(Point p, Point c, int r)
|
||||
{
|
||||
int dx = p.x - c.x;
|
||||
int dy = p.y - c.y;
|
||||
return dx*dx + dy*dy <= r*r ? 1 : 0;
|
||||
|
||||
}
|
||||
|
||||
//draw the hsv-plate
|
||||
void createPlate(Mat &im1, int radius)
|
||||
{
|
||||
Mat hsvImag(Size(radius << 1, radius << 1), CV_8UC3, Scalar(0, 0, 255));
|
||||
int w = hsvImag.cols;
|
||||
int h = hsvImag.rows;
|
||||
int cx = w >> 1;
|
||||
int cy = h >> 1;
|
||||
Point pt1(cx, 0);
|
||||
|
||||
for (int j = 0; j < w; j++)
|
||||
{
|
||||
for (int i = 0; i < h; i++)
|
||||
{
|
||||
Point pt2(j - cx, i - cy);
|
||||
if (inCircle(Point(0, 0), pt2, radius))
|
||||
{
|
||||
int theta = static_cast<int>(angle(pt1, pt2) * 180 / CV_PI);
|
||||
if (i > cx)
|
||||
{
|
||||
theta = -theta + 360;
|
||||
}
|
||||
hsvImag.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(theta / 2);
|
||||
hsvImag.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(module(pt2) / cx * 255);
|
||||
hsvImag.at<Vec3b>(i, j)[2] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cvtColor(hsvImag, im1, COLOR_HSV2BGR);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
import sys
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
def AddSlider(sliderName,windowName,minSlider,maxSlider,valDefault, update=[]):
|
||||
if update is None:
|
||||
cv.createTrackbar(sliderName, windowName, valDefault,maxSlider-minSlider+1)
|
||||
else:
|
||||
cv.createTrackbar(sliderName, windowName, valDefault,maxSlider-minSlider+1, update)
|
||||
cv.setTrackbarMin(sliderName, windowName, minSlider)
|
||||
cv.setTrackbarMax(sliderName, windowName, maxSlider)
|
||||
cv.setTrackbarPos(sliderName, windowName, valDefault)
|
||||
class Filtrage:
|
||||
def __init__(self):
|
||||
self.s =0
|
||||
self.alpha = 100
|
||||
self.omega = 100
|
||||
self.updateFiltre=True
|
||||
self.img=[]
|
||||
self.dximg=[]
|
||||
self.dyimg=[]
|
||||
self.module=[]
|
||||
def DericheFilter(self):
|
||||
self.dximg = cv.ximgproc.GradientDericheX( self.img, self.alpha/100., self.omega/1000. )
|
||||
self.dyimg = cv.ximgproc.GradientDericheY( self.img, self.alpha/100., self.omega/1000. )
|
||||
dx2=self.dximg*self.dximg
|
||||
dy2=self.dyimg*self.dyimg
|
||||
self.module = np.sqrt(dx2+dy2)
|
||||
cv.normalize(src=self.module,dst=self.module,norm_type=cv.NORM_MINMAX)
|
||||
def SlideBarDeriche(self):
|
||||
cv.namedWindow(self.filename)
|
||||
AddSlider("alpha",self.filename,1,400,self.alpha,self.UpdateAlpha)
|
||||
AddSlider("omega",self.filename,1,1000,self.omega,self.UpdateOmega)
|
||||
|
||||
def UpdateOmega(self,x ):
|
||||
self.updateFiltre=True
|
||||
self.omega=x
|
||||
def UpdateAlpha(self,x ):
|
||||
self.updateFiltre=True
|
||||
self.alpha=x
|
||||
def run(self,argv):
|
||||
# Load the source image
|
||||
self.filename = argv[0] if len(argv) > 0 else "../doc/pics/corridor_fld.jpg"
|
||||
self.img=cv.imread(self.filename,cv.IMREAD_GRAYSCALE)
|
||||
if self.img is None:
|
||||
print ('cannot read file')
|
||||
return
|
||||
self.SlideBarDeriche()
|
||||
while True:
|
||||
cv.imshow(self.filename,self.img)
|
||||
if self.updateFiltre:
|
||||
self.DericheFilter()
|
||||
cv.imshow("module",self.module)
|
||||
self.updateFiltre =False
|
||||
code = cv.waitKey(10)
|
||||
if code==27:
|
||||
break
|
||||
if __name__ == '__main__':
|
||||
Filtrage().run(sys.argv[1:])
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* By downloading, copying, installing or using the software you agree to this license.
|
||||
* If you do not agree to this license, do not download, install,
|
||||
* copy or use the software.
|
||||
*
|
||||
*
|
||||
* License Agreement
|
||||
* For Open Source Computer Vision Library
|
||||
* (3 - clause BSD License)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met :
|
||||
*
|
||||
* *Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and / or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the names of the copyright holders nor the names of the contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* This software is provided by the copyright holders and contributors "as is" and
|
||||
* any express or implied warranties, including, but not limited to, the implied
|
||||
* warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
* In no event shall copyright holders or contributors be liable for any direct,
|
||||
* indirect, incidental, special, exemplary, or consequential damages
|
||||
* (including, but not limited to, procurement of substitute goods or services;
|
||||
* loss of use, data, or profits; or business interruption) however caused
|
||||
* and on any theory of liability, whether in contract, strict liability,
|
||||
* or tort(including negligence or otherwise) arising in any way out of
|
||||
* the use of this software, even if advised of the possibility of such damage.
|
||||
*/
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
#include "opencv2/ximgproc/deriche_filter.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
int alDerive=100;
|
||||
int alMean=100;
|
||||
Ptr<Mat> img;
|
||||
const string & winName = "Gradient Modulus";
|
||||
|
||||
static void DisplayImage(Mat x,string s)
|
||||
{
|
||||
vector<Mat> sx;
|
||||
split(x, sx);
|
||||
vector<double> minVal(3), maxVal(3);
|
||||
for (size_t i = 0; i < sx.size(); i++)
|
||||
{
|
||||
minMaxLoc(sx[i], &minVal[i], &maxVal[i]);
|
||||
}
|
||||
maxVal[0] = *max_element(maxVal.begin(), maxVal.end());
|
||||
minVal[0] = *min_element(minVal.begin(), minVal.end());
|
||||
Mat uc;
|
||||
x.convertTo(uc, CV_8U,255/(maxVal[0]-minVal[0]),-255*minVal[0]/(maxVal[0]-minVal[0]));
|
||||
imshow(s, uc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function DericheFilter
|
||||
* @brief Trackbar callback
|
||||
*/
|
||||
static void DericheFilter(int, void*)
|
||||
{
|
||||
Mat dst;
|
||||
double d=alDerive/100.0,m=alMean/100.0;
|
||||
Mat rx,ry;
|
||||
GradientDericheX(*img.get(),rx,d,m);
|
||||
GradientDericheY(*img.get(),ry,d,m);
|
||||
DisplayImage(rx, "Gx");
|
||||
DisplayImage(ry, "Gy");
|
||||
add(rx.mul(rx),ry.mul(ry),dst);
|
||||
sqrt(dst,dst);
|
||||
DisplayImage(dst, winName );
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
Mat *m=new Mat;
|
||||
cv::CommandLineParser parser(argc, argv, "{help h | | show help message}{@input | | input image}");
|
||||
if (parser.has("help"))
|
||||
{
|
||||
parser.printMessage();
|
||||
return -1;
|
||||
}
|
||||
string input_image = parser.get<string>("@input");
|
||||
if (input_image.empty())
|
||||
{
|
||||
parser.printMessage();
|
||||
parser.printErrors();
|
||||
return -2;
|
||||
}
|
||||
if (argc==2)
|
||||
*m = imread(input_image);
|
||||
if (m->empty())
|
||||
{
|
||||
cout << "File not found or empty image\n";
|
||||
return -3;
|
||||
}
|
||||
imshow("Original", *m);
|
||||
img =Ptr<Mat>(m);
|
||||
namedWindow( winName, WINDOW_AUTOSIZE );
|
||||
/// Create a Trackbar for user to enter threshold
|
||||
createTrackbar( "Derive:",winName, &alDerive, 400, DericheFilter );
|
||||
createTrackbar( "Mean:", winName, &alMean, 400, DericheFilter );
|
||||
DericheFilter(0,NULL);
|
||||
waitKey();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,477 @@
|
||||
#include "opencv2/stereo.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/core/utility.hpp"
|
||||
#include "opencv2/ximgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
using namespace std;
|
||||
|
||||
Rect computeROI(Size2i src_sz, Ptr<StereoMatcher> matcher_instance);
|
||||
|
||||
const String keys =
|
||||
"{help h usage ? | | print this message }"
|
||||
"{@left |../data/aloeL.jpg | left view of the stereopair }"
|
||||
"{@right |../data/aloeR.jpg | right view of the stereopair }"
|
||||
"{GT |../data/aloeGT.png| optional ground-truth disparity (MPI-Sintel or Middlebury format) }"
|
||||
"{dst_path |None | optional path to save the resulting filtered disparity map }"
|
||||
"{dst_raw_path |None | optional path to save raw disparity map before filtering }"
|
||||
"{algorithm |bm | stereo matching method (bm or sgbm) }"
|
||||
"{filter |wls_conf | used post-filtering (wls_conf or wls_no_conf or fbs_conf) }"
|
||||
"{no-display | | don't display results }"
|
||||
"{no-downscale | | force stereo matching on full-sized views to improve quality }"
|
||||
"{dst_conf_path |None | optional path to save the confidence map used in filtering }"
|
||||
"{vis_mult |1.0 | coefficient used to scale disparity map visualizations }"
|
||||
"{max_disparity |160 | parameter of stereo matching }"
|
||||
"{window_size |-1 | parameter of stereo matching }"
|
||||
"{wls_lambda |8000.0 | parameter of wls post-filtering }"
|
||||
"{wls_sigma |1.5 | parameter of wls post-filtering }"
|
||||
"{fbs_spatial |16.0 | parameter of fbs post-filtering }"
|
||||
"{fbs_luma |8.0 | parameter of fbs post-filtering }"
|
||||
"{fbs_chroma |8.0 | parameter of fbs post-filtering }"
|
||||
"{fbs_lambda |128.0 | parameter of fbs post-filtering }"
|
||||
;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
CommandLineParser parser(argc,argv,keys);
|
||||
parser.about("Disparity Filtering Demo");
|
||||
if (parser.has("help"))
|
||||
{
|
||||
parser.printMessage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
String left_im = parser.get<String>(0);
|
||||
String right_im = parser.get<String>(1);
|
||||
String GT_path = parser.get<String>("GT");
|
||||
|
||||
String dst_path = parser.get<String>("dst_path");
|
||||
String dst_raw_path = parser.get<String>("dst_raw_path");
|
||||
String dst_conf_path = parser.get<String>("dst_conf_path");
|
||||
String algo = parser.get<String>("algorithm");
|
||||
String filter = parser.get<String>("filter");
|
||||
bool no_display = parser.has("no-display");
|
||||
bool no_downscale = parser.has("no-downscale");
|
||||
int max_disp = parser.get<int>("max_disparity");
|
||||
double lambda = parser.get<double>("wls_lambda");
|
||||
double sigma = parser.get<double>("wls_sigma");
|
||||
double fbs_spatial = parser.get<double>("fbs_spatial");
|
||||
double fbs_luma = parser.get<double>("fbs_luma");
|
||||
double fbs_chroma = parser.get<double>("fbs_chroma");
|
||||
double fbs_lambda = parser.get<double>("fbs_lambda");
|
||||
double vis_mult = parser.get<double>("vis_mult");
|
||||
|
||||
int wsize;
|
||||
if(parser.get<int>("window_size")>=0) //user provided window_size value
|
||||
wsize = parser.get<int>("window_size");
|
||||
else
|
||||
{
|
||||
if(algo=="sgbm")
|
||||
wsize = 3; //default window size for SGBM
|
||||
else if(!no_downscale && algo=="bm" && filter=="wls_conf")
|
||||
wsize = 7; //default window size for BM on downscaled views (downscaling is performed only for wls_conf)
|
||||
else
|
||||
wsize = 15; //default window size for BM on full-sized views
|
||||
}
|
||||
|
||||
if (!parser.check())
|
||||
{
|
||||
parser.printErrors();
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! [load_views]
|
||||
Mat left = imread(left_im ,IMREAD_COLOR);
|
||||
if ( left.empty() )
|
||||
{
|
||||
cout<<"Cannot read image file: "<<left_im;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Mat right = imread(right_im,IMREAD_COLOR);
|
||||
if ( right.empty() )
|
||||
{
|
||||
cout<<"Cannot read image file: "<<right_im;
|
||||
return -1;
|
||||
}
|
||||
//! [load_views]
|
||||
|
||||
bool noGT;
|
||||
Mat GT_disp;
|
||||
if (GT_path=="../data/aloeGT.png" && left_im!="../data/aloeL.jpg")
|
||||
noGT=true;
|
||||
else
|
||||
{
|
||||
noGT=false;
|
||||
if(readGT(GT_path,GT_disp)!=0)
|
||||
{
|
||||
cout<<"Cannot read ground truth image file: "<<GT_path<<endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Mat left_for_matcher, right_for_matcher;
|
||||
Mat left_disp,right_disp;
|
||||
Mat filtered_disp,solved_disp,solved_filtered_disp;
|
||||
Mat conf_map = Mat(left.rows,left.cols,CV_8U);
|
||||
conf_map = Scalar(255);
|
||||
Rect ROI;
|
||||
Ptr<DisparityWLSFilter> wls_filter;
|
||||
double matching_time, filtering_time;
|
||||
double solving_time = 0;
|
||||
if(max_disp<=0 || max_disp%16!=0)
|
||||
{
|
||||
cout<<"Incorrect max_disparity value: it should be positive and divisible by 16";
|
||||
return -1;
|
||||
}
|
||||
if(wsize<=0 || wsize%2!=1)
|
||||
{
|
||||
cout<<"Incorrect window_size value: it should be positive and odd";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(filter=="wls_conf") // filtering with confidence (significantly better quality than wls_no_conf)
|
||||
{
|
||||
if(!no_downscale)
|
||||
{
|
||||
// downscale the views to speed-up the matching stage, as we will need to compute both left
|
||||
// and right disparity maps for confidence map computation
|
||||
//! [downscale]
|
||||
max_disp/=2;
|
||||
if(max_disp%16!=0)
|
||||
max_disp += 16-(max_disp%16);
|
||||
resize(left ,left_for_matcher ,Size(),0.5,0.5, INTER_LINEAR_EXACT);
|
||||
resize(right,right_for_matcher,Size(),0.5,0.5, INTER_LINEAR_EXACT);
|
||||
//! [downscale]
|
||||
}
|
||||
else
|
||||
{
|
||||
left_for_matcher = left.clone();
|
||||
right_for_matcher = right.clone();
|
||||
}
|
||||
|
||||
if(algo=="bm")
|
||||
{
|
||||
//! [matching]
|
||||
Ptr<StereoBM> left_matcher = StereoBM::create(max_disp,wsize);
|
||||
wls_filter = createDisparityWLSFilter(left_matcher);
|
||||
Ptr<StereoMatcher> right_matcher = createRightMatcher(left_matcher);
|
||||
|
||||
cvtColor(left_for_matcher, left_for_matcher, COLOR_BGR2GRAY);
|
||||
cvtColor(right_for_matcher, right_for_matcher, COLOR_BGR2GRAY);
|
||||
|
||||
matching_time = (double)getTickCount();
|
||||
left_matcher-> compute(left_for_matcher, right_for_matcher,left_disp);
|
||||
right_matcher->compute(right_for_matcher,left_for_matcher, right_disp);
|
||||
matching_time = ((double)getTickCount() - matching_time)/getTickFrequency();
|
||||
//! [matching]
|
||||
}
|
||||
else if(algo=="sgbm")
|
||||
{
|
||||
Ptr<StereoSGBM> left_matcher = StereoSGBM::create(0,max_disp,wsize);
|
||||
left_matcher->setP1(24*wsize*wsize);
|
||||
left_matcher->setP2(96*wsize*wsize);
|
||||
left_matcher->setPreFilterCap(63);
|
||||
left_matcher->setMode(StereoSGBM::MODE_SGBM_3WAY);
|
||||
wls_filter = createDisparityWLSFilter(left_matcher);
|
||||
Ptr<StereoMatcher> right_matcher = createRightMatcher(left_matcher);
|
||||
|
||||
matching_time = (double)getTickCount();
|
||||
left_matcher-> compute(left_for_matcher, right_for_matcher,left_disp);
|
||||
right_matcher->compute(right_for_matcher,left_for_matcher, right_disp);
|
||||
matching_time = ((double)getTickCount() - matching_time)/getTickFrequency();
|
||||
}
|
||||
else
|
||||
{
|
||||
cout<<"Unsupported algorithm";
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! [filtering]
|
||||
wls_filter->setLambda(lambda);
|
||||
wls_filter->setSigmaColor(sigma);
|
||||
filtering_time = (double)getTickCount();
|
||||
wls_filter->filter(left_disp,left,filtered_disp,right_disp);
|
||||
filtering_time = ((double)getTickCount() - filtering_time)/getTickFrequency();
|
||||
//! [filtering]
|
||||
conf_map = wls_filter->getConfidenceMap();
|
||||
|
||||
// Get the ROI that was used in the last filter call:
|
||||
ROI = wls_filter->getROI();
|
||||
if(!no_downscale)
|
||||
{
|
||||
// upscale raw disparity and ROI back for a proper comparison:
|
||||
resize(left_disp,left_disp,Size(),2.0,2.0,INTER_LINEAR_EXACT);
|
||||
left_disp = left_disp*2.0;
|
||||
ROI = Rect(ROI.x*2,ROI.y*2,ROI.width*2,ROI.height*2);
|
||||
}
|
||||
}
|
||||
else if(filter=="fbs_conf") // filtering with fbs and confidence using also wls pre-processing
|
||||
{
|
||||
if(!no_downscale)
|
||||
{
|
||||
// downscale the views to speed-up the matching stage, as we will need to compute both left
|
||||
// and right disparity maps for confidence map computation
|
||||
//! [downscale_wls]
|
||||
max_disp/=2;
|
||||
if(max_disp%16!=0)
|
||||
max_disp += 16-(max_disp%16);
|
||||
resize(left ,left_for_matcher ,Size(),0.5,0.5);
|
||||
resize(right,right_for_matcher,Size(),0.5,0.5);
|
||||
//! [downscale_wls]
|
||||
}
|
||||
else
|
||||
{
|
||||
left_for_matcher = left.clone();
|
||||
right_for_matcher = right.clone();
|
||||
}
|
||||
|
||||
if(algo=="bm")
|
||||
{
|
||||
//! [matching_wls]
|
||||
Ptr<StereoBM> left_matcher = StereoBM::create(max_disp,wsize);
|
||||
wls_filter = createDisparityWLSFilter(left_matcher);
|
||||
Ptr<StereoMatcher> right_matcher = createRightMatcher(left_matcher);
|
||||
|
||||
cvtColor(left_for_matcher, left_for_matcher, COLOR_BGR2GRAY);
|
||||
cvtColor(right_for_matcher, right_for_matcher, COLOR_BGR2GRAY);
|
||||
|
||||
matching_time = (double)getTickCount();
|
||||
left_matcher-> compute(left_for_matcher, right_for_matcher,left_disp);
|
||||
right_matcher->compute(right_for_matcher,left_for_matcher, right_disp);
|
||||
matching_time = ((double)getTickCount() - matching_time)/getTickFrequency();
|
||||
//! [matching_wls]
|
||||
}
|
||||
else if(algo=="sgbm")
|
||||
{
|
||||
Ptr<StereoSGBM> left_matcher = StereoSGBM::create(0,max_disp,wsize);
|
||||
left_matcher->setP1(24*wsize*wsize);
|
||||
left_matcher->setP2(96*wsize*wsize);
|
||||
left_matcher->setPreFilterCap(63);
|
||||
left_matcher->setMode(StereoSGBM::MODE_SGBM_3WAY);
|
||||
wls_filter = createDisparityWLSFilter(left_matcher);
|
||||
Ptr<StereoMatcher> right_matcher = createRightMatcher(left_matcher);
|
||||
|
||||
matching_time = (double)getTickCount();
|
||||
left_matcher-> compute(left_for_matcher, right_for_matcher,left_disp);
|
||||
right_matcher->compute(right_for_matcher,left_for_matcher, right_disp);
|
||||
matching_time = ((double)getTickCount() - matching_time)/getTickFrequency();
|
||||
}
|
||||
else
|
||||
{
|
||||
cout<<"Unsupported algorithm";
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! [filtering_wls]
|
||||
wls_filter->setLambda(lambda);
|
||||
wls_filter->setSigmaColor(sigma);
|
||||
filtering_time = (double)getTickCount();
|
||||
wls_filter->filter(left_disp,left,filtered_disp,right_disp);
|
||||
filtering_time = ((double)getTickCount() - filtering_time)/getTickFrequency();
|
||||
//! [filtering_wls]
|
||||
|
||||
conf_map = wls_filter->getConfidenceMap();
|
||||
|
||||
Mat left_disp_resized;
|
||||
resize(left_disp,left_disp_resized,left.size());
|
||||
|
||||
// Get the ROI that was used in the last filter call:
|
||||
ROI = wls_filter->getROI();
|
||||
if(!no_downscale)
|
||||
{
|
||||
// upscale raw disparity and ROI back for a proper comparison:
|
||||
resize(left_disp,left_disp,Size(),2.0,2.0);
|
||||
left_disp = left_disp*2.0;
|
||||
left_disp_resized = left_disp_resized*2.0;
|
||||
ROI = Rect(ROI.x*2,ROI.y*2,ROI.width*2,ROI.height*2);
|
||||
}
|
||||
|
||||
#ifdef HAVE_EIGEN
|
||||
//! [filtering_fbs]
|
||||
solving_time = (double)getTickCount();
|
||||
fastBilateralSolverFilter(left, left_disp_resized, conf_map/255.0f, solved_disp, fbs_spatial, fbs_luma, fbs_chroma, fbs_lambda);
|
||||
solving_time = ((double)getTickCount() - solving_time)/getTickFrequency();
|
||||
//! [filtering_fbs]
|
||||
|
||||
//! [filtering_wls2fbs]
|
||||
fastBilateralSolverFilter(left, filtered_disp, conf_map/255.0f, solved_filtered_disp, fbs_spatial, fbs_luma, fbs_chroma, fbs_lambda);
|
||||
//! [filtering_wls2fbs]
|
||||
#else
|
||||
(void)fbs_spatial;
|
||||
(void)fbs_luma;
|
||||
(void)fbs_chroma;
|
||||
(void)fbs_lambda;
|
||||
#endif
|
||||
}
|
||||
else if(filter=="wls_no_conf")
|
||||
{
|
||||
/* There is no convenience function for the case of filtering with no confidence, so we
|
||||
will need to set the ROI and matcher parameters manually */
|
||||
|
||||
left_for_matcher = left.clone();
|
||||
right_for_matcher = right.clone();
|
||||
|
||||
if(algo=="bm")
|
||||
{
|
||||
Ptr<StereoBM> matcher = StereoBM::create(max_disp,wsize);
|
||||
matcher->setTextureThreshold(0);
|
||||
matcher->setUniquenessRatio(0);
|
||||
cvtColor(left_for_matcher, left_for_matcher, COLOR_BGR2GRAY);
|
||||
cvtColor(right_for_matcher, right_for_matcher, COLOR_BGR2GRAY);
|
||||
ROI = computeROI(left_for_matcher.size(),matcher);
|
||||
wls_filter = createDisparityWLSFilterGeneric(false);
|
||||
wls_filter->setDepthDiscontinuityRadius((int)ceil(0.33*wsize));
|
||||
|
||||
matching_time = (double)getTickCount();
|
||||
matcher->compute(left_for_matcher,right_for_matcher,left_disp);
|
||||
matching_time = ((double)getTickCount() - matching_time)/getTickFrequency();
|
||||
}
|
||||
else if(algo=="sgbm")
|
||||
{
|
||||
Ptr<StereoSGBM> matcher = StereoSGBM::create(0,max_disp,wsize);
|
||||
matcher->setUniquenessRatio(0);
|
||||
matcher->setDisp12MaxDiff(1000000);
|
||||
matcher->setSpeckleWindowSize(0);
|
||||
matcher->setP1(24*wsize*wsize);
|
||||
matcher->setP2(96*wsize*wsize);
|
||||
matcher->setMode(StereoSGBM::MODE_SGBM_3WAY);
|
||||
ROI = computeROI(left_for_matcher.size(),matcher);
|
||||
wls_filter = createDisparityWLSFilterGeneric(false);
|
||||
wls_filter->setDepthDiscontinuityRadius((int)ceil(0.5*wsize));
|
||||
|
||||
matching_time = (double)getTickCount();
|
||||
matcher->compute(left_for_matcher,right_for_matcher,left_disp);
|
||||
matching_time = ((double)getTickCount() - matching_time)/getTickFrequency();
|
||||
}
|
||||
else
|
||||
{
|
||||
cout<<"Unsupported algorithm";
|
||||
return -1;
|
||||
}
|
||||
|
||||
wls_filter->setLambda(lambda);
|
||||
wls_filter->setSigmaColor(sigma);
|
||||
filtering_time = (double)getTickCount();
|
||||
wls_filter->filter(left_disp,left,filtered_disp,Mat(),ROI);
|
||||
filtering_time = ((double)getTickCount() - filtering_time)/getTickFrequency();
|
||||
}
|
||||
else
|
||||
{
|
||||
cout<<"Unsupported filter";
|
||||
return -1;
|
||||
}
|
||||
|
||||
//collect and print all the stats:
|
||||
cout.precision(2);
|
||||
cout<<"Matching time: "<<matching_time<<"s"<<endl;
|
||||
cout<<"Filtering time: "<<filtering_time<<"s"<<endl;
|
||||
cout<<"Solving time: "<<solving_time<<"s"<<endl;
|
||||
cout<<endl;
|
||||
|
||||
double MSE_before,percent_bad_before,MSE_after,percent_bad_after;
|
||||
if(!noGT)
|
||||
{
|
||||
MSE_before = computeMSE(GT_disp,left_disp,ROI);
|
||||
percent_bad_before = computeBadPixelPercent(GT_disp,left_disp,ROI);
|
||||
MSE_after = computeMSE(GT_disp,filtered_disp,ROI);
|
||||
percent_bad_after = computeBadPixelPercent(GT_disp,filtered_disp,ROI);
|
||||
|
||||
cout.precision(5);
|
||||
cout<<"MSE before filtering: "<<MSE_before<<endl;
|
||||
cout<<"MSE after filtering: "<<MSE_after<<endl;
|
||||
cout<<endl;
|
||||
cout.precision(3);
|
||||
cout<<"Percent of bad pixels before filtering: "<<percent_bad_before<<endl;
|
||||
cout<<"Percent of bad pixels after filtering: "<<percent_bad_after<<endl;
|
||||
}
|
||||
|
||||
if(dst_path!="None")
|
||||
{
|
||||
Mat filtered_disp_vis;
|
||||
getDisparityVis(filtered_disp,filtered_disp_vis,vis_mult);
|
||||
imwrite(dst_path,filtered_disp_vis);
|
||||
}
|
||||
if(dst_raw_path!="None")
|
||||
{
|
||||
Mat raw_disp_vis;
|
||||
getDisparityVis(left_disp,raw_disp_vis,vis_mult);
|
||||
imwrite(dst_raw_path,raw_disp_vis);
|
||||
}
|
||||
if(dst_conf_path!="None")
|
||||
{
|
||||
imwrite(dst_conf_path,conf_map);
|
||||
}
|
||||
|
||||
if(!no_display)
|
||||
{
|
||||
namedWindow("left", WINDOW_AUTOSIZE);
|
||||
imshow("left", left);
|
||||
namedWindow("right", WINDOW_AUTOSIZE);
|
||||
imshow("right", right);
|
||||
|
||||
if(!noGT)
|
||||
{
|
||||
Mat GT_disp_vis;
|
||||
getDisparityVis(GT_disp,GT_disp_vis,vis_mult);
|
||||
namedWindow("ground-truth disparity", WINDOW_AUTOSIZE);
|
||||
imshow("ground-truth disparity", GT_disp_vis);
|
||||
}
|
||||
|
||||
//! [visualization]
|
||||
Mat raw_disp_vis;
|
||||
getDisparityVis(left_disp,raw_disp_vis,vis_mult);
|
||||
namedWindow("raw disparity", WINDOW_AUTOSIZE);
|
||||
imshow("raw disparity", raw_disp_vis);
|
||||
Mat filtered_disp_vis;
|
||||
getDisparityVis(filtered_disp,filtered_disp_vis,vis_mult);
|
||||
namedWindow("filtered disparity", WINDOW_AUTOSIZE);
|
||||
imshow("filtered disparity", filtered_disp_vis);
|
||||
|
||||
if(!solved_disp.empty())
|
||||
{
|
||||
Mat solved_disp_vis;
|
||||
getDisparityVis(solved_disp,solved_disp_vis,vis_mult);
|
||||
namedWindow("solved disparity", WINDOW_AUTOSIZE);
|
||||
imshow("solved disparity", solved_disp_vis);
|
||||
|
||||
Mat solved_filtered_disp_vis;
|
||||
getDisparityVis(solved_filtered_disp,solved_filtered_disp_vis,vis_mult);
|
||||
namedWindow("solved wls disparity", WINDOW_AUTOSIZE);
|
||||
imshow("solved wls disparity", solved_filtered_disp_vis);
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
char key = (char)waitKey();
|
||||
if( key == 27 || key == 'q' || key == 'Q') // 'ESC'
|
||||
break;
|
||||
}
|
||||
//! [visualization]
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Rect computeROI(Size2i src_sz, Ptr<StereoMatcher> matcher_instance)
|
||||
{
|
||||
int min_disparity = matcher_instance->getMinDisparity();
|
||||
int num_disparities = matcher_instance->getNumDisparities();
|
||||
int block_size = matcher_instance->getBlockSize();
|
||||
|
||||
int bs2 = block_size/2;
|
||||
int minD = min_disparity, maxD = min_disparity + num_disparities - 1;
|
||||
|
||||
int xmin = maxD + bs2;
|
||||
int xmax = src_sz.width + minD - bs2;
|
||||
int ymin = bs2;
|
||||
int ymax = src_sz.height - bs2;
|
||||
|
||||
Rect r(xmin, ymin, xmax - xmin, ymax - ymin);
|
||||
return r;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
'''
|
||||
This example script illustrates how to use cv.ximgproc.EdgeDrawing class.
|
||||
|
||||
It uses the OpenCV library to load an image, and then use the EdgeDrawing class
|
||||
to detect edges, lines, and ellipses. The detected features are then drawn and displayed.
|
||||
|
||||
The main loop allows the user changing parameters of EdgeDrawing by pressing following keys:
|
||||
|
||||
to toggle the grayscale conversion press 'space' key
|
||||
to increase MinPathLength value press '/' key
|
||||
to decrease MinPathLength value press '*' key
|
||||
to increase MinLineLength value press '+' key
|
||||
to decrease MinLineLength value press '-' key
|
||||
to toggle NFAValidation value press 'n' key
|
||||
to toggle PFmode value press 'p' key
|
||||
to save parameters to file press 's' key
|
||||
to load parameters from file press 'l' key
|
||||
|
||||
The program exits when the Esc key is pressed.
|
||||
|
||||
Usage:
|
||||
ed.py [<image_name>]
|
||||
image argument defaults to board.jpg
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import random as rng
|
||||
import sys
|
||||
|
||||
def EdgeDrawingDemo(src, ed, EDParams, convert_to_gray):
|
||||
rng.seed(12345)
|
||||
ssrc = np.zeros_like(src)
|
||||
lsrc = src.copy()
|
||||
esrc = src.copy()
|
||||
|
||||
img_to_detect = cv.cvtColor(src, cv.COLOR_BGR2GRAY) if convert_to_gray else src
|
||||
|
||||
cv.imshow("source image", img_to_detect)
|
||||
|
||||
print("")
|
||||
print("convert_to_gray:", convert_to_gray)
|
||||
print("MinPathLength:", EDParams.MinPathLength)
|
||||
print("MinLineLength:", EDParams.MinLineLength)
|
||||
print("PFmode:", EDParams.PFmode)
|
||||
print("NFAValidation:", EDParams.NFAValidation)
|
||||
|
||||
tm = cv.TickMeter()
|
||||
tm.start()
|
||||
|
||||
# Detect edges
|
||||
# you should call this before detectLines() and detectEllipses()
|
||||
ed.detectEdges(img_to_detect)
|
||||
|
||||
segments = ed.getSegments()
|
||||
lines = ed.detectLines()
|
||||
ellipses = ed.detectEllipses()
|
||||
|
||||
tm.stop()
|
||||
|
||||
print("Detection time : {:.2f} ms. using the parameters above".format(tm.getTimeMilli()))
|
||||
|
||||
# Draw detected edge segments
|
||||
for segment in segments:
|
||||
color = (rng.randint(0, 256), rng.randint(0, 256), rng.randint(0, 256))
|
||||
cv.polylines(ssrc, [segment], False, color, 1, cv.LINE_8)
|
||||
|
||||
cv.imshow("detected edge segments", ssrc)
|
||||
|
||||
# Draw detected lines
|
||||
if lines is not None: # Check if the lines have been found and only then iterate over these and add them to the image
|
||||
lines = np.uint16(np.around(lines))
|
||||
for line in lines:
|
||||
cv.line(lsrc, (line[0][0], line[0][1]), (line[0][2], line[0][3]), (0, 0, 255), 1, cv.LINE_AA)
|
||||
|
||||
cv.imshow("detected lines", lsrc)
|
||||
|
||||
# Draw detected circles and ellipses
|
||||
if ellipses is not None: # Check if circles and ellipses have been found and only then iterate over these and add them to the image
|
||||
for ellipse in ellipses:
|
||||
center = (int(ellipse[0][0]), int(ellipse[0][1]))
|
||||
axes = (int(ellipse[0][2] + ellipse[0][3]), int(ellipse[0][2] + ellipse[0][4]))
|
||||
angle = ellipse[0][5]
|
||||
|
||||
color = (0, 255, 0) if ellipse[0][2] == 0 else (0, 0, 255)
|
||||
|
||||
cv.ellipse(esrc, center, axes, angle, 0, 360, color, 2, cv.LINE_AA)
|
||||
|
||||
cv.imshow("detected circles and ellipses", esrc)
|
||||
|
||||
def main():
|
||||
try:
|
||||
fn = sys.argv[1]
|
||||
except IndexError:
|
||||
fn = 'board.jpg'
|
||||
src = cv.imread(cv.samples.findFile(fn))
|
||||
if src is None:
|
||||
print("Error loading image")
|
||||
return
|
||||
|
||||
ed = cv.ximgproc.createEdgeDrawing()
|
||||
|
||||
# Set parameters (refer to the documentation for all parameters)
|
||||
EDParams = cv.ximgproc_EdgeDrawing_Params()
|
||||
EDParams.MinPathLength = 10 # try changing this value by pressing '/' and '*' keys
|
||||
EDParams.MinLineLength = 10 # try changing this value by pressing '+' and '-' keys
|
||||
EDParams.PFmode = False # default value is False, try switching by pressing 'p' key
|
||||
EDParams.NFAValidation = True # default value is True, try switching by pressing 'n' key
|
||||
|
||||
convert_to_gray = True
|
||||
key = 0
|
||||
|
||||
while key != 27:
|
||||
ed.setParams(EDParams)
|
||||
EdgeDrawingDemo(src, ed, EDParams, convert_to_gray)
|
||||
key = cv.waitKey()
|
||||
if key == 32: # space key
|
||||
convert_to_gray = not convert_to_gray
|
||||
if key == 112: # 'p' key
|
||||
EDParams.PFmode = not EDParams.PFmode
|
||||
if key == 110: # 'n' key
|
||||
EDParams.NFAValidation = not EDParams.NFAValidation
|
||||
if key == 43: # '+' key
|
||||
EDParams.MinLineLength = EDParams.MinLineLength + 5
|
||||
if key == 45: # '-' key
|
||||
EDParams.MinLineLength = max(0, EDParams.MinLineLength - 5)
|
||||
if key == 47: # '/' key
|
||||
EDParams.MinPathLength = EDParams.MinPathLength + 20
|
||||
if key == 42: # '*' key
|
||||
EDParams.MinPathLength = max(0, EDParams.MinPathLength - 20)
|
||||
if key == 115: # 's' key
|
||||
fs = cv.FileStorage("ed-params.xml",cv.FileStorage_WRITE)
|
||||
EDParams.write(fs)
|
||||
fs.release()
|
||||
print("parameters saved to ed-params.xml")
|
||||
if key == 108: # 'l' key
|
||||
fs = cv.FileStorage("ed-params.xml",cv.FileStorage_READ)
|
||||
if fs.isOpened():
|
||||
EDParams.read(fs.root())
|
||||
fs.release()
|
||||
print("parameters loaded from ed-params.xml")
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(__doc__)
|
||||
main()
|
||||
cv.destroyAllWindows()
|
||||
@@ -0,0 +1,185 @@
|
||||
/* edge_drawing.cpp
|
||||
|
||||
This example illustrates how to use cv.ximgproc.EdgeDrawing class.
|
||||
|
||||
It uses the OpenCV library to load an image, and then use the EdgeDrawing class
|
||||
to detect edges, lines, and ellipses. The detected features are then drawn and displayed.
|
||||
|
||||
The main loop allows the user changing parameters of EdgeDrawing by pressing following keys:
|
||||
|
||||
to toggle the grayscale conversion press 'space' key
|
||||
to increase MinPathLength value press '/' key
|
||||
to decrease MinPathLength value press '*' key
|
||||
to increase MinLineLength value press '+' key
|
||||
to decrease MinLineLength value press '-' key
|
||||
to toggle NFAValidation value press 'n' key
|
||||
to toggle PFmode value press 'p' key
|
||||
to save parameters to file press 's' key
|
||||
to load parameters from file press 'l' key
|
||||
|
||||
The program exits when the Esc key is pressed.
|
||||
*/
|
||||
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
#include <iostream>
|
||||
|
||||
void EdgeDrawingDemo(const cv::Mat src, cv::Ptr<cv::ximgproc::EdgeDrawing> ed, bool convert_to_gray);
|
||||
|
||||
void EdgeDrawingDemo(const cv::Mat src, cv::Ptr<cv::ximgproc::EdgeDrawing> ed, bool convert_to_gray)
|
||||
{
|
||||
cv::Mat ssrc = cv::Mat::zeros(src.size(), src.type());
|
||||
cv::Mat lsrc = src.clone();
|
||||
cv::Mat esrc = src.clone();
|
||||
|
||||
std::cout << std::endl << "convert_to_gray: " << convert_to_gray << std::endl;
|
||||
std::cout << "MinPathLength: " << ed->params.MinPathLength << std::endl;
|
||||
std::cout << "MinLineLength: " << ed->params.MinLineLength << std::endl;
|
||||
std::cout << "PFmode: " << ed->params.PFmode << std::endl;
|
||||
std::cout << "NFAValidation: " << ed->params.NFAValidation << std::endl;
|
||||
|
||||
cv::TickMeter tm;
|
||||
tm.start();
|
||||
|
||||
cv::Mat img_to_detect;
|
||||
|
||||
if (convert_to_gray)
|
||||
{
|
||||
cv::cvtColor(src, img_to_detect, cv::COLOR_BGR2GRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
img_to_detect = src;
|
||||
}
|
||||
|
||||
cv::imshow("source image", img_to_detect);
|
||||
|
||||
tm.start();
|
||||
|
||||
// Detect edges
|
||||
ed->detectEdges(img_to_detect);
|
||||
|
||||
std::vector<std::vector<cv::Point>> segments = ed->getSegments();
|
||||
std::vector<cv::Vec4f> lines;
|
||||
ed->detectLines(lines);
|
||||
std::vector<cv::Vec6d> ellipses;
|
||||
ed->detectEllipses(ellipses);
|
||||
|
||||
tm.stop();
|
||||
|
||||
cv::RNG& rng = cv::theRNG();
|
||||
cv::setRNGSeed(0);
|
||||
|
||||
// Draw detected edge segments
|
||||
for (const auto& segment : segments)
|
||||
{
|
||||
cv::Scalar color(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
|
||||
cv::polylines(ssrc, segment, false, color, 1, cv::LINE_8);
|
||||
}
|
||||
|
||||
cv::imshow("detected edge segments", ssrc);
|
||||
|
||||
// Draw detected lines
|
||||
if (!lines.empty()) // Check if the lines have been found and only then iterate over these and add them to the image
|
||||
{
|
||||
for (size_t i = 0; i < lines.size(); i++)
|
||||
{
|
||||
cv::line(lsrc, cv::Point2d(lines[i][0], lines[i][1]), cv::Point2d(lines[i][2], lines[i][3]), cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
|
||||
}
|
||||
}
|
||||
|
||||
cv::imshow("detected lines", lsrc);
|
||||
|
||||
// Draw detected circles and ellipses
|
||||
if (!ellipses.empty()) // Check if circles and ellipses have been found and only then iterate over these and add them to the image
|
||||
{
|
||||
for (const auto& ellipse : ellipses)
|
||||
{
|
||||
cv::Point center((int)ellipse[0], (int)ellipse[1]);
|
||||
cv::Size axes((int)ellipse[2] + (int)ellipse[3], (int)ellipse[2] + (int)ellipse[4]);
|
||||
double angle(ellipse[5]);
|
||||
cv::Scalar color = (ellipse[2] == 0) ? cv::Scalar(0, 255, 0) : cv::Scalar(0, 0, 255);
|
||||
cv::ellipse(esrc, center, axes, angle, 0, 360, color, 1, cv::LINE_AA);
|
||||
}
|
||||
}
|
||||
|
||||
cv::imshow("detected circles and ellipses", esrc);
|
||||
std::cout << "Total Detection Time : " << tm.getTimeMilli() << "ms." << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string filename = (argc > 1) ? argv[1] : "board.jpg";
|
||||
cv::Mat src = cv::imread(cv::samples::findFile(filename));
|
||||
|
||||
if (src.empty())
|
||||
{
|
||||
std::cerr << "Error: Could not open or find the image!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cv::Ptr<cv::ximgproc::EdgeDrawing> ed = cv::ximgproc::createEdgeDrawing();
|
||||
|
||||
// Set parameters (refer to the documentation for all parameters)
|
||||
ed->params.MinPathLength = 10; // try changing this value by pressing '/' and '*' keys
|
||||
ed->params.MinLineLength = 10; // try changing this value by pressing '+' and '-' keys
|
||||
ed->params.PFmode = false; // default value is false, try switching by pressing 'p' key
|
||||
ed->params.NFAValidation = true; // default value is true, try switching by pressing 'n' key
|
||||
|
||||
bool convert_to_gray = true;
|
||||
int key = 0;
|
||||
|
||||
while (key != 27)
|
||||
{
|
||||
EdgeDrawingDemo(src, ed, convert_to_gray);
|
||||
key = cv::waitKey(0);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case 32: // space key
|
||||
convert_to_gray = !convert_to_gray;
|
||||
break;
|
||||
case 'p': // 'p' key
|
||||
ed->params.PFmode = !ed->params.PFmode;
|
||||
break;
|
||||
case 'n': // 'n' key
|
||||
ed->params.NFAValidation = !ed->params.NFAValidation;
|
||||
break;
|
||||
case '+': // '+' key
|
||||
ed->params.MinLineLength = std::max(0, ed->params.MinLineLength + 5);
|
||||
break;
|
||||
case '-': // '-' key
|
||||
ed->params.MinLineLength = std::max(0, ed->params.MinLineLength - 5);
|
||||
break;
|
||||
case '/': // '/' key
|
||||
ed->params.MinPathLength += 20;
|
||||
break;
|
||||
case '*': // '*' key
|
||||
ed->params.MinPathLength = std::max(0, ed->params.MinPathLength - 20);
|
||||
break;
|
||||
case 's': // 's' key
|
||||
{
|
||||
cv::FileStorage fs("ed-params.xml", cv::FileStorage::WRITE);
|
||||
ed->params.write(fs);
|
||||
fs.release();
|
||||
std::cout << "Parameters saved to ed-params.xml" << std::endl;
|
||||
}
|
||||
break;
|
||||
case 'l': // 'l' key
|
||||
{
|
||||
cv::FileStorage fs("ed-params.xml", cv::FileStorage::READ);
|
||||
if (fs.isOpened())
|
||||
{
|
||||
ed->params.read(fs.root());
|
||||
fs.release();
|
||||
std::cout << "Parameters loaded from ed-params.xml" << std::endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
By downloading, copying, installing or using the software you agree to this
|
||||
license. If you do not agree to this license, do not download, install,
|
||||
copy or use the software.
|
||||
License Agreement
|
||||
For Open Source Computer Vision Library
|
||||
(3-clause BSD License)
|
||||
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
Third party copyrights are property of their respective owners.
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of the contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
This software is provided by the copyright holders and contributors "as is" and
|
||||
any express or implied warranties, including, but not limited to, the implied
|
||||
warranties of merchantability and fitness for a particular purpose are
|
||||
disclaimed. In no event shall copyright holders or contributors be liable for
|
||||
any direct, indirect, incidental, special, exemplary, or consequential damages
|
||||
(including, but not limited to, procurement of substitute goods or services;
|
||||
loss of use, data, or profits; or business interruption) however caused
|
||||
and on any theory of liability, whether in contract, strict liability,
|
||||
or tort (including negligence or otherwise) arising in any way out of
|
||||
the use of this software, even if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include "opencv2/ximgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
|
||||
static void help()
|
||||
{
|
||||
std::cout << std::endl <<
|
||||
"This sample demonstrates structured edge detection and edgeboxes." << std::endl <<
|
||||
"Usage:" << std::endl <<
|
||||
"./edgeboxes_demo [<model>] [<input_image>]" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
|
||||
Ptr<StructuredEdgeDetection> pDollar = createStructuredEdgeDetection(argv[1]);
|
||||
|
||||
Mat im;
|
||||
im = imread(argv[2]);
|
||||
|
||||
Mat rgb_im;
|
||||
cvtColor(im, rgb_im, COLOR_BGR2RGB);
|
||||
rgb_im.convertTo(rgb_im, CV_32F, 1.0 / 255.0f);
|
||||
|
||||
Mat edge_im;
|
||||
pDollar->detectEdges(rgb_im, edge_im);
|
||||
|
||||
// computes orientation from edge map
|
||||
Mat O;
|
||||
pDollar->computeOrientation(edge_im, O);
|
||||
|
||||
// apply edge nms
|
||||
Mat edge_nms;
|
||||
pDollar->edgesNms(edge_im, O, edge_nms, 2, 0, 1, true);
|
||||
|
||||
std::vector<Rect> boxes;
|
||||
Ptr<EdgeBoxes> edgeboxes = createEdgeBoxes();
|
||||
edgeboxes->setMaxBoxes(30);
|
||||
edgeboxes->getBoundingBoxes(edge_nms, O, boxes);
|
||||
|
||||
for(int i = 0; i < (int)boxes.size(); i++)
|
||||
{
|
||||
Point p1(boxes[i].x, boxes[i].y), p2(boxes[i].x + boxes[i].width, boxes[i].y + boxes[i].height);
|
||||
Scalar color(0, 255, 0);
|
||||
rectangle(im, p1, p2, color, 1);
|
||||
}
|
||||
|
||||
imshow("Edge", edge_im);
|
||||
imshow("Nms", edge_nms);
|
||||
imshow("Image & boxes", im);
|
||||
waitKey(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
This sample demonstrates structured edge detection and edgeboxes.
|
||||
Usage:
|
||||
edgeboxes_demo.py [<model>] [<input_image>]
|
||||
'''
|
||||
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(__doc__)
|
||||
|
||||
model = sys.argv[1]
|
||||
im = cv.imread(sys.argv[2])
|
||||
|
||||
edge_detection = cv.ximgproc.createStructuredEdgeDetection(model)
|
||||
rgb_im = cv.cvtColor(im, cv.COLOR_BGR2RGB)
|
||||
edges = edge_detection.detectEdges(np.float32(rgb_im) / 255.0)
|
||||
|
||||
orimap = edge_detection.computeOrientation(edges)
|
||||
edges = edge_detection.edgesNms(edges, orimap)
|
||||
|
||||
edge_boxes = cv.ximgproc.createEdgeBoxes()
|
||||
edge_boxes.setMaxBoxes(30)
|
||||
boxes = edge_boxes.getBoundingBoxes(edges, orimap)
|
||||
boxes, scores = edge_boxes.getBoundingBoxes(edges, orimap)
|
||||
|
||||
if len(boxes) > 0:
|
||||
boxes_scores = zip(boxes, scores)
|
||||
for b_s in boxes_scores:
|
||||
box = b_s[0]
|
||||
x, y, w, h = box
|
||||
cv.rectangle(im, (x, y), (x+w, y+h), (0, 255, 0), 1, cv.LINE_AA)
|
||||
score = b_s[1][0]
|
||||
cv.putText(im, "{:.2f}".format(score), (x, y), cv.FONT_HERSHEY_PLAIN, 0.8, (255, 255, 255), 1, cv.LINE_AA)
|
||||
print("Box at (x,y)=({:d},{:d}); score={:f}".format(x, y, score))
|
||||
|
||||
cv.imshow("edges", edges)
|
||||
cv.imshow("edgeboxes", im)
|
||||
cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
@@ -0,0 +1,42 @@
|
||||
#include <iostream>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
#include <string>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cv::CommandLineParser parser(
|
||||
argc, argv,
|
||||
"{help h ? | | help message}"
|
||||
"{@image | | Image filename to process }");
|
||||
if (parser.has("help") || !parser.has("@image"))
|
||||
{
|
||||
parser.printMessage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Load image from first parameter
|
||||
std::string filename = parser.get<std::string>("@image");
|
||||
Mat image = imread(filename, 1), res;
|
||||
|
||||
if (!image.data)
|
||||
{
|
||||
std::cerr << "No image data at " << filename << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
// Before filtering
|
||||
imshow("Original image", image);
|
||||
waitKey(0);
|
||||
|
||||
// Initialize filter. Kernel size 5x5, threshold 20
|
||||
ximgproc::edgePreservingFilter(image, res, 9, 20);
|
||||
|
||||
// After filtering
|
||||
imshow("Filtered image", res);
|
||||
waitKey(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2015, Smart Engines Ltd, all rights reserved.
|
||||
// Copyright (C) 2015, Institute for Information Transmission Problems of the Russian Academy of Sciences (Kharkevich Institute), all rights reserved.
|
||||
// Copyright (C) 2015, Dmitry Nikolaev, Simon Karpenko, Michail Aliev, Elena Kuznetsova, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <vector>
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
using namespace std;
|
||||
|
||||
static void help()
|
||||
{
|
||||
cout << "\nThis program demonstrates line finding with the Fast Hough transform.\n"
|
||||
"Usage:\n"
|
||||
"./fasthoughtransform\n"
|
||||
"<image_name>, default is '../../../samples/data/building.jpg'\n"
|
||||
"<fht_image_depth>, default is " << CV_32S << "\n"
|
||||
"<fht_angle_range>, default is " << 6 << " (@see cv::AngleRangeOption)\n"
|
||||
"<fht_operator>, default is " << 2 << " (@see cv::HoughOp)\n"
|
||||
"<fht_makeskew>, default is " << 1 << "(@see cv::HoughDeskewOption)" << endl;
|
||||
}
|
||||
|
||||
static bool parseArgs(int argc, const char **argv,
|
||||
Mat &img,
|
||||
int &houghDepth,
|
||||
int &houghAngleRange,
|
||||
int &houghOperator,
|
||||
int &houghSkew)
|
||||
{
|
||||
if (argc > 6)
|
||||
{
|
||||
cout << "Too many arguments" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *filename = argc >= 2 ? argv[1]
|
||||
: "../../../samples/data/building.jpg";
|
||||
img = imread(filename, 0);
|
||||
if (img.empty())
|
||||
{
|
||||
cout << "Failed to load image from '" << filename << "'" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
houghDepth = argc >= 3 ? atoi(argv[2]) : CV_32S;
|
||||
houghAngleRange = argc >= 4 ? atoi(argv[3]) : 6;//ARO_315_135
|
||||
houghOperator = argc >= 5 ? atoi(argv[4]) : 2;//FHT_ADD
|
||||
houghSkew = argc >= 6 ? atoi(argv[5]) : 1;//HDO_DESKEW
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getEdges(const Mat &src, Mat &dst)
|
||||
{
|
||||
Mat ucharSingleSrc;
|
||||
src.convertTo(ucharSingleSrc, CV_8UC1);
|
||||
|
||||
Canny(ucharSingleSrc, dst, 50, 200, 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool fht(const Mat &src, Mat &dst,
|
||||
int dstDepth, int angleRange, int op, int skew)
|
||||
{
|
||||
clock_t clocks = clock();
|
||||
|
||||
FastHoughTransform(src, dst, dstDepth, angleRange, op, skew);
|
||||
|
||||
clocks = clock() - clocks;
|
||||
double secs = (double)clocks / CLOCKS_PER_SEC;
|
||||
cout << std::setprecision(2) << "FastHoughTransform finished in " << secs
|
||||
<< " seconds" << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool rel(pair<T, Point> const &a, pair<T, Point> const &b)
|
||||
{
|
||||
return a.first > b.first;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool incIfGreater(const T& a, const T& b, int *value)
|
||||
{
|
||||
if (!value || a < b)
|
||||
return false;
|
||||
if (a > b)
|
||||
++(*value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const int MAX_LEN = 10000;
|
||||
|
||||
template<typename T>
|
||||
bool getLocalExtr(vector<Vec4i> &lines,
|
||||
const Mat &src,
|
||||
const Mat &fht,
|
||||
float minWeight,
|
||||
int maxCount)
|
||||
{
|
||||
vector<pair<T, Point> > weightedPoints;
|
||||
for (int y = 0; y < fht.rows; ++y)
|
||||
{
|
||||
if (weightedPoints.size() > MAX_LEN)
|
||||
break;
|
||||
|
||||
T const *pLine = (T *)fht.ptr(max(y - 1, 0));
|
||||
T const *cLine = (T *)fht.ptr(y);
|
||||
T const *nLine = (T *)fht.ptr(min(y + 1, fht.rows - 1));
|
||||
|
||||
for (int x = 0; x < fht.cols; ++x)
|
||||
{
|
||||
if (weightedPoints.size() > MAX_LEN)
|
||||
break;
|
||||
|
||||
T const value = cLine[x];
|
||||
if (value >= minWeight)
|
||||
{
|
||||
int isLocalMax = 0;
|
||||
for (int xx = max(x - 1, 0);
|
||||
xx <= min(x + 1, fht.cols - 1);
|
||||
++xx)
|
||||
{
|
||||
if (!incIfGreater(value, pLine[xx], &isLocalMax) ||
|
||||
!incIfGreater(value, cLine[xx], &isLocalMax) ||
|
||||
!incIfGreater(value, nLine[xx], &isLocalMax))
|
||||
{
|
||||
isLocalMax = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isLocalMax > 0)
|
||||
weightedPoints.push_back(make_pair(value, Point(x, y)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (weightedPoints.empty())
|
||||
return true;
|
||||
|
||||
sort(weightedPoints.begin(), weightedPoints.end(), &rel<T>);
|
||||
weightedPoints.resize(min(static_cast<int>(weightedPoints.size()),
|
||||
maxCount));
|
||||
|
||||
for (size_t i = 0; i < weightedPoints.size(); ++i)
|
||||
{
|
||||
lines.push_back(HoughPoint2Line(weightedPoints[i].second, src));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getLocalExtr(vector<Vec4i> &lines,
|
||||
const Mat &src,
|
||||
const Mat &fht,
|
||||
float minWeight,
|
||||
int maxCount)
|
||||
{
|
||||
int const depth = CV_MAT_DEPTH(fht.type());
|
||||
switch (depth)
|
||||
{
|
||||
case 0:
|
||||
return getLocalExtr<uchar>(lines, src, fht, minWeight, maxCount);
|
||||
case 1:
|
||||
return getLocalExtr<schar>(lines, src, fht, minWeight, maxCount);
|
||||
case 2:
|
||||
return getLocalExtr<ushort>(lines, src, fht, minWeight, maxCount);
|
||||
case 3:
|
||||
return getLocalExtr<short>(lines, src, fht, minWeight, maxCount);
|
||||
case 4:
|
||||
return getLocalExtr<int>(lines, src, fht, minWeight, maxCount);
|
||||
case 5:
|
||||
return getLocalExtr<float>(lines, src, fht, minWeight, maxCount);
|
||||
case 6:
|
||||
return getLocalExtr<double>(lines, src, fht, minWeight, maxCount);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void rescale(Mat const &src, Mat &dst,
|
||||
int const maxHeight=500,
|
||||
int const maxWidth = 1000)
|
||||
{
|
||||
double scale = min(min(static_cast<double>(maxWidth) / src.cols,
|
||||
static_cast<double>(maxHeight) / src.rows), 1.0);
|
||||
resize(src, dst, Size(), scale, scale, INTER_LINEAR_EXACT);
|
||||
}
|
||||
|
||||
static void showHumanReadableImg(string const &name, Mat const &img)
|
||||
{
|
||||
Mat ucharImg;
|
||||
img.convertTo(ucharImg, CV_MAKETYPE(CV_8U, img.channels()));
|
||||
rescale(ucharImg, ucharImg);
|
||||
imshow(name, ucharImg);
|
||||
}
|
||||
|
||||
static void showFht(Mat const &fht)
|
||||
{
|
||||
double minv(0), maxv(0);
|
||||
minMaxLoc(fht, &minv, &maxv);
|
||||
Mat ucharFht;
|
||||
fht.convertTo(ucharFht, CV_MAKETYPE(CV_8U, fht.channels()),
|
||||
255.0 / (maxv + minv), minv / (maxv + minv));
|
||||
rescale(ucharFht, ucharFht);
|
||||
imshow("fast hough transform", ucharFht);
|
||||
}
|
||||
|
||||
static void showLines(Mat const &src, vector<Vec4i> const &lines)
|
||||
{
|
||||
Mat bgrSrc;
|
||||
cvtColor(src, bgrSrc, COLOR_GRAY2BGR);
|
||||
|
||||
for (size_t i = 0; i < lines.size(); ++i)
|
||||
{
|
||||
Vec4i const &l = lines[i];
|
||||
line(bgrSrc, Point(l[0], l[1]), Point(l[2], l[3]),
|
||||
Scalar(0, 0, 255), 1, LINE_AA);
|
||||
}
|
||||
|
||||
rescale(bgrSrc, bgrSrc);
|
||||
imshow("lines", bgrSrc);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
Mat src;
|
||||
int depth(0);
|
||||
int angleRange(0);
|
||||
int op(0);
|
||||
int skew(0);
|
||||
|
||||
if (!parseArgs(argc, argv, src, depth, angleRange, op, skew))
|
||||
{
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
showHumanReadableImg("src", src);
|
||||
|
||||
Mat canny;
|
||||
if (!getEdges(src, canny))
|
||||
{
|
||||
cout << "Failed to select canny edges";
|
||||
return -2;
|
||||
}
|
||||
showHumanReadableImg("canny", canny);
|
||||
|
||||
Mat hough;
|
||||
if (!fht(canny, hough, depth, angleRange, op, skew))
|
||||
{
|
||||
cout << "Failed to compute Fast Hough Transform";
|
||||
return -2;
|
||||
}
|
||||
showFht(hough);
|
||||
|
||||
vector<Vec4i> lines;
|
||||
if (!getLocalExtr(lines, canny, hough,
|
||||
static_cast<float>(255 * 0.3 * min(src.rows, src.cols)),
|
||||
50))
|
||||
{
|
||||
cout << "Failed to find local maximums on FHT image";
|
||||
return -2;
|
||||
}
|
||||
showLines(canny, lines);
|
||||
|
||||
waitKey();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "opencv2/core/utility.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/ximgproc.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
int main( int argc, const char** argv)
|
||||
{
|
||||
float alpha = 1.0f;
|
||||
float sigma = 0.02f;
|
||||
int rows0 = 480;
|
||||
int niters = 10;
|
||||
Mat frame, src, dst;
|
||||
|
||||
const char* window_name = "Anisodiff : Exponential Flux";
|
||||
|
||||
VideoCapture cap;
|
||||
if( argc > 1 )
|
||||
cap.open(argv[1]);
|
||||
else
|
||||
cap.open(0);
|
||||
|
||||
if (!cap.isOpened())
|
||||
{
|
||||
printf("Cannot initialize video capturing\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create a window
|
||||
namedWindow(window_name, 1);
|
||||
|
||||
// create a toolbar
|
||||
createTrackbar("No. of time steps", window_name, &niters, 30, 0);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
cap >> frame;
|
||||
if( frame.empty() )
|
||||
break;
|
||||
|
||||
if( frame.rows <= rows0 )
|
||||
src = frame;
|
||||
else
|
||||
resize(frame, src, Size(cvRound(480.*frame.cols/frame.rows), 480), 0, 0, INTER_LINEAR_EXACT);
|
||||
|
||||
float t = (float)getTickCount();
|
||||
ximgproc::anisotropicDiffusion(src, dst, alpha, sigma, niters);
|
||||
t = (float)getTickCount() - t;
|
||||
printf("time: %.1fms\n", t*1000./getTickFrequency());
|
||||
imshow(window_name, dst);
|
||||
|
||||
// Wait for a key stroke; the same function arranges events processing
|
||||
char c = (char)waitKey(30);
|
||||
if(c >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include <iostream>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
int main() {
|
||||
|
||||
// load image
|
||||
Mat img = imread(samples::findFile("stuff.jpg"), IMREAD_COLOR);
|
||||
|
||||
// check if image is loaded
|
||||
if (img.empty()) {
|
||||
std::cout << "fail to open image" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// create output array
|
||||
std::vector<Vec6f> ells;
|
||||
|
||||
// test ellipse detection
|
||||
cv::ximgproc::findEllipses(img, ells, 0.4f, 0.7f, 0.02f);
|
||||
|
||||
// print output
|
||||
for (unsigned i = 0; i < ells.size(); i++) {
|
||||
Vec6f ell = ells[i];
|
||||
std::cout << ell << std::endl;
|
||||
Scalar color(0, 0, 255);
|
||||
// draw ellipse on image
|
||||
ellipse(
|
||||
img,
|
||||
Point(cvRound(ell[0]), cvRound(ell[1])),
|
||||
Size(cvRound(ell[2]), cvRound(ell[3])),
|
||||
ell[5] * 180 / CV_PI, 0.0, 360.0, color, 3
|
||||
);
|
||||
}
|
||||
|
||||
// show image
|
||||
imshow("result", img);
|
||||
waitKey();
|
||||
|
||||
// end
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
'''
|
||||
This example illustrates how to use cv.ximgproc.findEllipses function.
|
||||
|
||||
Usage:
|
||||
find_ellipses.py [<image_name>]
|
||||
image argument defaults to stuff.jpg
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import sys
|
||||
import math
|
||||
|
||||
def main():
|
||||
try:
|
||||
fn = sys.argv[1]
|
||||
except IndexError:
|
||||
fn = 'stuff.jpg'
|
||||
|
||||
src = cv.imread(cv.samples.findFile(fn))
|
||||
cv.imshow("source", src)
|
||||
|
||||
ells = cv.ximgproc.findEllipses(src,scoreThreshold = 0.4, reliabilityThreshold = 0.7, centerDistanceThreshold = 0.02)
|
||||
|
||||
if ells is not None:
|
||||
for i in range(len(ells)):
|
||||
center = (int(ells[i][0][0]), int(ells[i][0][1]))
|
||||
axes = (int(ells[i][0][2]),int(ells[i][0][3]))
|
||||
angle = ells[i][0][5] * 180 / math.pi
|
||||
color = (0, 0, 255)
|
||||
cv.ellipse(src, center, axes, angle,0, 360, color, 2, cv.LINE_AA)
|
||||
|
||||
cv.imshow("detected ellipses", src)
|
||||
cv.waitKey(0)
|
||||
print('Done')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(__doc__)
|
||||
main()
|
||||
cv.destroyAllWindows()
|
||||
@@ -0,0 +1,29 @@
|
||||
# USAGE - How to run this code ?
|
||||
# python find_shapes.py --image shapes.png
|
||||
#python findredlinedpolygonfromgooglemaps.py --image stanford.png
|
||||
|
||||
import numpy as np
|
||||
import argparse
|
||||
import cv2 as cv
|
||||
|
||||
# construct the argument parse and parse the arguments
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("-i", "--image", help = "path to the image file")
|
||||
args = vars(ap.parse_args())
|
||||
|
||||
# load the image
|
||||
image = cv.imread(args["image"])
|
||||
lower = np.array([20,0,155])
|
||||
upper = np.array([255,120,250])
|
||||
shapeMask = cv.inRange(image, lower, upper)
|
||||
|
||||
# find the contours in the mask
|
||||
(cnts, _) = cv.findContours(shapeMask.copy(), cv.RETR_EXTERNAL,
|
||||
cv.CHAIN_APPROX_SIMPLE)
|
||||
cv.imshow("Mask", shapeMask)
|
||||
|
||||
# loop over the contours
|
||||
for c in cnts:
|
||||
cv.drawContours(image, [c], -1, (0, 255, 0), 2)
|
||||
cv.imshow("Image", image)
|
||||
cv.waitKey(0)
|
||||
@@ -0,0 +1,78 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/ximgproc.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
string in;
|
||||
CommandLineParser parser(argc, argv, "{@input|corridor.jpg|input image}{help h||show help message}");
|
||||
if (parser.has("help"))
|
||||
{
|
||||
parser.printMessage();
|
||||
return 0;
|
||||
}
|
||||
in = samples::findFile(parser.get<string>("@input"));
|
||||
|
||||
Mat image = imread(in, IMREAD_GRAYSCALE);
|
||||
|
||||
if( image.empty() )
|
||||
{
|
||||
parser.printMessage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create FLD detector
|
||||
// Param Default value Description
|
||||
// length_threshold 10 - Segments shorter than this will be discarded
|
||||
// distance_threshold 1.41421356 - A point placed from a hypothesis line
|
||||
// segment farther than this will be
|
||||
// regarded as an outlier
|
||||
// canny_th1 50 - First threshold for
|
||||
// hysteresis procedure in Canny()
|
||||
// canny_th2 50 - Second threshold for
|
||||
// hysteresis procedure in Canny()
|
||||
// canny_aperture_size 3 - Aperturesize for the sobel operator in Canny().
|
||||
// If zero, Canny() is not applied and the input
|
||||
// image is taken as an edge image.
|
||||
// do_merge false - If true, incremental merging of segments
|
||||
// will be performed
|
||||
int length_threshold = 10;
|
||||
float distance_threshold = 1.41421356f;
|
||||
double canny_th1 = 50.0;
|
||||
double canny_th2 = 50.0;
|
||||
int canny_aperture_size = 3;
|
||||
bool do_merge = false;
|
||||
Ptr<FastLineDetector> fld = createFastLineDetector(length_threshold,
|
||||
distance_threshold, canny_th1, canny_th2, canny_aperture_size,
|
||||
do_merge);
|
||||
vector<Vec4f> lines;
|
||||
|
||||
// Because of some CPU's power strategy, it seems that the first running of
|
||||
// an algorithm takes much longer. So here we run the algorithm 5 times
|
||||
// to see the algorithm's processing time with sufficiently warmed-up
|
||||
// CPU performance.
|
||||
for (int run_count = 0; run_count < 5; run_count++) {
|
||||
double freq = getTickFrequency();
|
||||
lines.clear();
|
||||
int64 start = getTickCount();
|
||||
// Detect the lines with FLD
|
||||
fld->detect(image, lines);
|
||||
double duration_ms = double(getTickCount() - start) * 1000 / freq;
|
||||
cout << "Elapsed time for FLD " << duration_ms << " ms." << endl;
|
||||
}
|
||||
|
||||
// Show found lines with FLD
|
||||
Mat line_image_fld(image);
|
||||
fld->drawSegments(line_image_fld, lines);
|
||||
imshow("FLD result", line_image_fld);
|
||||
waitKey();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/geometry.hpp>
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
struct ThParameters {
|
||||
int levelNoise;
|
||||
int angle;
|
||||
int scale10;
|
||||
int origin;
|
||||
int xg;
|
||||
int yg;
|
||||
bool update;
|
||||
} ;
|
||||
|
||||
static vector<Point> NoisyPolygon(vector<Point> pRef, double n);
|
||||
static void UpdateShape(int , void *r);
|
||||
static void AddSlider(String sliderName, String windowName, int minSlider, int maxSlider, int valDefault, int *valSlider, void(*f)(int, void *), void *r);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
vector<Point> ctrRef;
|
||||
vector<Point> ctrRotate, ctrNoisy, ctrNoisyRotate, ctrNoisyRotateShift;
|
||||
// build a shape with 5 vertex
|
||||
ctrRef.push_back(Point(250,250)); ctrRef.push_back(Point(400, 250));
|
||||
ctrRef.push_back(Point(400, 300)); ctrRef.push_back(Point(250, 300));ctrRef.push_back(Point(180, 270));
|
||||
Point cg(0,0);
|
||||
for (int i=0;i<static_cast<int>(ctrRef.size());i++)
|
||||
cg+=ctrRef[i];
|
||||
cg.x /= static_cast<int>(ctrRef.size());
|
||||
cg.y /= static_cast<int>(ctrRef.size());
|
||||
ThParameters p;
|
||||
p.levelNoise=6;
|
||||
p.angle=45;
|
||||
p.scale10=5;
|
||||
p.origin=10;
|
||||
p.xg=150;
|
||||
p.yg=150;
|
||||
p.update=true;
|
||||
namedWindow("FD Curve matching");
|
||||
// A rotation with center at (150,150) of angle 45 degrees and a scaling of 5/10
|
||||
AddSlider("Noise", "FD Curve matching", 0, 20, p.levelNoise, &p.levelNoise, UpdateShape, &p);
|
||||
AddSlider("Angle", "FD Curve matching", 0, 359, p.angle, &p.angle, UpdateShape, &p);
|
||||
AddSlider("Scale", "FD Curve matching", 5, 100, p.scale10, &p.scale10, UpdateShape, &p);
|
||||
AddSlider("Origin%%", "FD Curve matching", 0, 100, p.origin, &p.origin, UpdateShape, &p);
|
||||
AddSlider("Xg", "FD Curve matching", 150, 450, p.xg, &p.xg, UpdateShape, &p);
|
||||
AddSlider("Yg", "FD Curve matching", 150, 450, p.yg, &p.yg, UpdateShape, &p);
|
||||
int code=0;
|
||||
double dist;
|
||||
vector<vector<Point> > c;
|
||||
Mat img;
|
||||
cout << "******************** PRESS g TO MATCH CURVES *************\n";
|
||||
do
|
||||
{
|
||||
code = waitKey(30);
|
||||
if (p.update)
|
||||
{
|
||||
Mat r = getRotationMatrix2D(Point(p.xg, p.yg), p.angle, 10.0/ p.scale10);
|
||||
ctrNoisy= NoisyPolygon(ctrRef,static_cast<double>(p.levelNoise));
|
||||
cv::transform(ctrNoisy, ctrNoisyRotate, r);
|
||||
ctrNoisyRotateShift.clear();
|
||||
for (int i=0;i<static_cast<int>(ctrNoisy.size());i++)
|
||||
ctrNoisyRotateShift.push_back(ctrNoisyRotate[(i+(p.origin*ctrNoisy.size())/100)% ctrNoisy.size()]);
|
||||
// To draw contour using drawcontours
|
||||
c.clear();
|
||||
c.push_back(ctrRef);
|
||||
c.push_back(ctrNoisyRotateShift);
|
||||
p.update = false;
|
||||
Rect rglobal;
|
||||
for (int i = 0; i < static_cast<int>(c.size()); i++)
|
||||
{
|
||||
rglobal = boundingRect(c[i]) | rglobal;
|
||||
}
|
||||
rglobal.width += 10;
|
||||
rglobal.height += 10;
|
||||
img = Mat::zeros(2 * rglobal.height, 2 * rglobal.width, CV_8UC(3));
|
||||
drawContours(img, c, 0, Scalar(255,0,0));
|
||||
drawContours(img, c, 1, Scalar(0, 255, 0));
|
||||
circle(img, c[0][0], 5, Scalar(255, 0, 0));
|
||||
circle(img, c[1][0], 5, Scalar(0, 255, 0));
|
||||
imshow("FD Curve matching", img);
|
||||
}
|
||||
if (code == 'd')
|
||||
{
|
||||
destroyWindow("FD Curve matching");
|
||||
namedWindow("FD Curve matching");
|
||||
// A rotation with center at (150,150) of angle 45 degrees and a scaling of 5/10
|
||||
AddSlider("Noise", "FD Curve matching", 0, 20, p.levelNoise, &p.levelNoise, UpdateShape, &p);
|
||||
AddSlider("Angle", "FD Curve matching", 0, 359, p.angle, &p.angle, UpdateShape, &p);
|
||||
AddSlider("Scale", "FD Curve matching", 5, 100, p.scale10, &p.scale10, UpdateShape, &p);
|
||||
AddSlider("Origin%%", "FD Curve matching", 0, 100, p.origin, &p.origin, UpdateShape, &p);
|
||||
AddSlider("Xg", "FD Curve matching", 150, 450, p.xg, &p.xg, UpdateShape, &p);
|
||||
AddSlider("Yg", "FD Curve matching", 150, 450, p.yg, &p.yg, UpdateShape, &p);
|
||||
|
||||
}
|
||||
if (code == 'g')
|
||||
{
|
||||
ximgproc::ContourFitting fit;
|
||||
vector<Point2f> ctrRef2d, ctrRot2d;
|
||||
// sampling contour we want 256 points
|
||||
ximgproc::contourSampling(ctrRef, ctrRef2d, 256); // use a mat
|
||||
ximgproc::contourSampling(ctrNoisyRotateShift, ctrRot2d, 256); // use a vector of points
|
||||
fit.setFDSize(16);
|
||||
Mat t;
|
||||
fit.estimateTransformation(ctrRot2d, ctrRef2d, t, &dist, false);
|
||||
cout << "Transform *********\n "<<"Origin = "<< 1-t.at<double>(0,0) <<" expected "<< p.origin/100.0 <<" ("<< ctrNoisy.size()<<")\n";
|
||||
cout << "Angle = " << t.at<double>(0, 1) * 180 / M_PI << " expected " << p.angle <<"\n";
|
||||
cout << "Scale = " << t.at<double>(0, 2) << " expected " << p.scale10 / 10.0 << "\n";
|
||||
Mat dst;
|
||||
ximgproc::transformFD(ctrRot2d, t, dst, false);
|
||||
c.push_back(dst);
|
||||
drawContours(img, c, 2, Scalar(0,255,255));
|
||||
circle(img, c[2][0], 5, Scalar(0, 255, 255));
|
||||
imshow("FD Curve matching", img);
|
||||
}
|
||||
}
|
||||
while (code!=27);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
vector<Point> NoisyPolygon(vector<Point> pRef, double n)
|
||||
{
|
||||
RNG rng;
|
||||
vector<Point> c;
|
||||
vector<Point> p = pRef;
|
||||
vector<vector<Point> > contour;
|
||||
for (int i = 0; i<static_cast<int>(p.size()); i++)
|
||||
p[i] += Point(Point2d(n*rng.uniform((double)-1, (double)1), n*rng.uniform((double)-1, (double)1)));
|
||||
if (n==0)
|
||||
return p;
|
||||
c.push_back(p[0]);
|
||||
int minX = p[0].x, maxX = p[0].x, minY = p[0].y, maxY = p[0].y;
|
||||
for (int i = 0; i <static_cast<int>(p.size()); i++)
|
||||
{
|
||||
int next = i + 1;
|
||||
if (next == static_cast<int>(p.size()))
|
||||
next = 0;
|
||||
Point2d u = p[next] - p[i];
|
||||
int d = static_cast<int>(norm(u));
|
||||
double a = atan2(u.y, u.x);
|
||||
int step = 1;
|
||||
if (n != 0)
|
||||
step = static_cast<int>(d / n);
|
||||
for (int j = 1; j<d; j += max(step, 1))
|
||||
{
|
||||
Point pNew;
|
||||
do
|
||||
{
|
||||
|
||||
Point2d pAct = (u*j) / static_cast<double>(d);
|
||||
double r = n*rng.uniform((double)0, (double)1);
|
||||
double theta = a + rng.uniform(0., 2 * CV_PI);
|
||||
pNew = Point(Point2d(r*cos(theta) + pAct.x + p[i].x, r*sin(theta) + pAct.y + p[i].y));
|
||||
} while (pNew.x<0 || pNew.y<0);
|
||||
if (pNew.x<minX)
|
||||
minX = pNew.x;
|
||||
if (pNew.x>maxX)
|
||||
maxX = pNew.x;
|
||||
if (pNew.y<minY)
|
||||
minY = pNew.y;
|
||||
if (pNew.y>maxY)
|
||||
maxY = pNew.y;
|
||||
c.push_back(pNew);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void UpdateShape(int , void *r)
|
||||
{
|
||||
((ThParameters *)r)->update = true;
|
||||
}
|
||||
|
||||
void AddSlider(String sliderName, String windowName, int minSlider, int maxSlider, int valDefault, int *valSlider, void(*f)(int, void *), void *r)
|
||||
{
|
||||
createTrackbar(sliderName, windowName, valSlider, 1, f, r);
|
||||
setTrackbarMin(sliderName, windowName, minSlider);
|
||||
setTrackbarMax(sliderName, windowName, maxSlider);
|
||||
setTrackbarPos(sliderName, windowName, valDefault);
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import math
|
||||
|
||||
class ThParameters:
|
||||
def __init__(self):
|
||||
self.levelNoise=6
|
||||
self.angle=45
|
||||
self.scale10=5
|
||||
self.origin=10
|
||||
self.xg=150
|
||||
self.yg=150
|
||||
self.update=True
|
||||
|
||||
def UpdateShape(x ):
|
||||
p.update = True
|
||||
|
||||
def union(a,b):
|
||||
x = min(a[0], b[0])
|
||||
y = min(a[1], b[1])
|
||||
w = max(a[0]+a[2], b[0]+b[2]) - x
|
||||
h = max(a[1]+a[3], b[1]+b[3]) - y
|
||||
return (x, y, w, h)
|
||||
|
||||
def intersection(a,b):
|
||||
x = max(a[0], b[0])
|
||||
y = max(a[1], b[1])
|
||||
w = min(a[0]+a[2], b[0]+b[2]) - x
|
||||
h = min(a[1]+a[3], b[1]+b[3]) - y
|
||||
if w<0 or h<0: return () # or (0,0,0,0) ?
|
||||
return (x, y, w, h)
|
||||
|
||||
def NoisyPolygon(pRef,n):
|
||||
# vector<Point> c
|
||||
p = pRef;
|
||||
# vector<vector<Point> > contour;
|
||||
p = p+n*np.random.random_sample((p.shape[0],p.shape[1]))-n/2.0
|
||||
if (n==0):
|
||||
return p
|
||||
c = np.empty(shape=[0, 2])
|
||||
minX = p[0][0]
|
||||
maxX = p[0][0]
|
||||
minY = p[0][1]
|
||||
maxY = p[0][1]
|
||||
for i in range( 0,p.shape[0]):
|
||||
next = i + 1;
|
||||
if (next == p.shape[0]):
|
||||
next = 0;
|
||||
u = p[next] - p[i]
|
||||
d = int(cv.norm(u))
|
||||
a = np.arctan2(u[1], u[0])
|
||||
step = 1
|
||||
if (n != 0):
|
||||
step = d // n
|
||||
for j in range( 1,int(d),int(max(step, 1))):
|
||||
while True:
|
||||
pAct = (u*j) / (d)
|
||||
r = n*np.random.random_sample()
|
||||
theta = a + 2*math.pi*np.random.random_sample()
|
||||
# pNew = Point(Point2d(r*cos(theta) + pAct.x + p[i].x, r*sin(theta) + pAct.y + p[i].y));
|
||||
pNew = np.array([(r*np.cos(theta) + pAct[0] + p[i][0], r*np.sin(theta) + pAct[1] + p[i][1])])
|
||||
if (pNew[0][0]>=0 and pNew[0][1]>=0):
|
||||
break
|
||||
if (pNew[0][0]<minX):
|
||||
minX = pNew[0][0]
|
||||
if (pNew[0][0]>maxX):
|
||||
maxX = pNew[0][0]
|
||||
if (pNew[0][1]<minY):
|
||||
minY = pNew[0][1]
|
||||
if (pNew[0][1]>maxY):
|
||||
maxY = pNew[0][1]
|
||||
c = np.append(c,pNew,axis = 0)
|
||||
return c
|
||||
|
||||
#static vector<Point> NoisyPolygon(vector<Point> pRef, double n);
|
||||
#static void UpdateShape(int , void *r);
|
||||
#static void AddSlider(String sliderName, String windowName, int minSlider, int maxSlider, int valDefault, int *valSlider, void(*f)(int, void *), void *r);
|
||||
def AddSlider(sliderName,windowName,minSlider,maxSlider,valDefault, update):
|
||||
cv.createTrackbar(sliderName, windowName, valDefault,maxSlider-minSlider+1, update)
|
||||
cv.setTrackbarMin(sliderName, windowName, minSlider)
|
||||
cv.setTrackbarMax(sliderName, windowName, maxSlider)
|
||||
cv.setTrackbarPos(sliderName, windowName, valDefault)
|
||||
|
||||
# vector<Point> ctrRef;
|
||||
# vector<Point> ctrRotate, ctrNoisy, ctrNoisyRotate, ctrNoisyRotateShift;
|
||||
# // build a shape with 5 vertex
|
||||
ctrRef = np.array([(250,250),(400, 250),(400, 300),(250, 300),(180, 270)])
|
||||
cg = np.mean(ctrRef,axis=0)
|
||||
p=ThParameters()
|
||||
cv.namedWindow("FD Curve matching");
|
||||
# A rotation with center at (150,150) of angle 45 degrees and a scaling of 5/10
|
||||
AddSlider("Noise", "FD Curve matching", 0, 20, p.levelNoise, UpdateShape)
|
||||
AddSlider("Angle", "FD Curve matching", 0, 359, p.angle, UpdateShape)
|
||||
AddSlider("Scale", "FD Curve matching", 5, 100, p.scale10, UpdateShape)
|
||||
AddSlider("Origin", "FD Curve matching", 0, 100, p.origin, UpdateShape)
|
||||
AddSlider("Xg", "FD Curve matching", 150, 450, p.xg, UpdateShape)
|
||||
AddSlider("Yg", "FD Curve matching", 150, 450, p.yg, UpdateShape)
|
||||
code = 0
|
||||
img = np.zeros((300,512,3), np.uint8)
|
||||
print ("******************** PRESS g TO MATCH CURVES *************\n")
|
||||
|
||||
while (code!=27):
|
||||
code = cv.waitKey(60)
|
||||
if p.update:
|
||||
p.levelNoise=cv.getTrackbarPos('Noise','FD Curve matching')
|
||||
p.angle=cv.getTrackbarPos('Angle','FD Curve matching')
|
||||
p.scale10=cv.getTrackbarPos('Scale','FD Curve matching')
|
||||
p.origin=cv.getTrackbarPos('Origin','FD Curve matching')
|
||||
p.xg=cv.getTrackbarPos('Xg','FD Curve matching')
|
||||
p.yg=cv.getTrackbarPos('Yg','FD Curve matching')
|
||||
|
||||
r = cv.getRotationMatrix2D((p.xg, p.yg), angle=p.angle, scale=10.0/ p.scale10);
|
||||
ctrNoisy= NoisyPolygon(ctrRef,p.levelNoise)
|
||||
ctrNoisy1 = np.reshape(ctrNoisy,(ctrNoisy.shape[0],1,2))
|
||||
ctrNoisyRotate = cv.transform(ctrNoisy1,r)
|
||||
ctrNoisyRotateShift = np.empty([ctrNoisyRotate.shape[0],1,2],dtype=np.int32)
|
||||
for i in range(0,ctrNoisy.shape[0]):
|
||||
k=(i+(p.origin*ctrNoisy.shape[0])//100)% ctrNoisyRotate.shape[0]
|
||||
ctrNoisyRotateShift[i] = ctrNoisyRotate[k]
|
||||
# To draw contour using drawcontours
|
||||
cc= np.reshape(ctrNoisyRotateShift,[ctrNoisyRotateShift.shape[0],2])
|
||||
c = [ ctrRef,cc]
|
||||
p.update = False;
|
||||
rglobal =(0,0,0,0)
|
||||
for i in range(0,2):
|
||||
r = cv.boundingRect(c[i])
|
||||
rglobal = union(rglobal,r)
|
||||
r = list(rglobal)
|
||||
r[2] = r[2]+10
|
||||
r[3] = r[3]+10
|
||||
rglobal = tuple(r)
|
||||
img = np.zeros((2 * rglobal[3], 2 * rglobal[2], 3), np.uint8)
|
||||
cv.drawContours(img, c, 0, (255,0,0),1);
|
||||
cv.drawContours(img, c, 1, (0, 255, 0),1);
|
||||
cv.circle(img, tuple(c[0][0]), 5, (255, 0, 0),3);
|
||||
cv.circle(img, tuple(c[1][0]), 5, (0, 255, 0),3);
|
||||
cv.imshow("FD Curve matching", img);
|
||||
if code == ord('d') :
|
||||
cv.destroyWindow("FD Curve matching");
|
||||
cv.namedWindow("FD Curve matching");
|
||||
# A rotation with center at (150,150) of angle 45 degrees and a scaling of 5/10
|
||||
AddSlider("Noise", "FD Curve matching", 0, 20, p.levelNoise, UpdateShape)
|
||||
AddSlider("Angle", "FD Curve matching", 0, 359, p.angle, UpdateShape)
|
||||
AddSlider("Scale", "FD Curve matching", 5, 100, p.scale10, UpdateShape)
|
||||
AddSlider("Origin%%", "FD Curve matching", 0, 100, p.origin, UpdateShape)
|
||||
AddSlider("Xg", "FD Curve matching", 150, 450, p.xg, UpdateShape)
|
||||
AddSlider("Yg", "FD Curve matching", 150, 450, p.yg, UpdateShape)
|
||||
if code == ord('g'):
|
||||
fit = cv.ximgproc.createContourFitting(1024,16);
|
||||
# sampling contour we want 256 points
|
||||
cn= np.reshape(ctrRef,[ctrRef.shape[0],1,2])
|
||||
|
||||
ctrRef2d = cv.ximgproc.contourSampling(cn, 256)
|
||||
ctrRot2d = cv.ximgproc.contourSampling(ctrNoisyRotateShift, 256)
|
||||
fit.setFDSize(16)
|
||||
c1 = ctrRef2d
|
||||
c2 = ctrRot2d
|
||||
alphaPhiST, dist = fit.estimateTransformation(ctrRot2d, ctrRef2d)
|
||||
print( "Transform *********\n Origin = ", 1-alphaPhiST[0,0] ," expected ", p.origin / 100. ,"\n")
|
||||
print( "Angle = ", alphaPhiST[0,1] * 180 / math.pi ," expected " , p.angle,"\n")
|
||||
print( "Scale = " ,alphaPhiST[0,2] ," expected " , p.scale10 / 10.0 , "\n")
|
||||
dst = cv.ximgproc.transformFD(ctrRot2d, alphaPhiST,cn, False);
|
||||
ctmp= np.reshape(dst,[dst.shape[0],2])
|
||||
cdst=ctmp.astype(int)
|
||||
|
||||
c = [ ctrRef,cc,cdst]
|
||||
cv.drawContours(img, c, 2, (0,0,255),1);
|
||||
cv.circle(img, (int(c[2][0][0]),int(c[2][0][1])), 5, (0, 0, 255),5);
|
||||
cv.imshow("FD Curve matching", img);
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
By downloading, copying, installing or using the software you agree to this
|
||||
license. If you do not agree to this license, do not download, install,
|
||||
copy or use the software.
|
||||
License Agreement
|
||||
For Open Source Computer Vision Library
|
||||
(3-clause BSD License)
|
||||
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
Third party copyrights are property of their respective owners.
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of the contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
This software is provided by the copyright holders and contributors "as is" and
|
||||
any express or implied warranties, including, but not limited to, the implied
|
||||
warranties of merchantability and fitness for a particular purpose are
|
||||
disclaimed. In no event shall copyright holders or contributors be liable for
|
||||
any direct, indirect, incidental, special, exemplary, or consequential damages
|
||||
(including, but not limited to, procurement of substitute goods or services;
|
||||
loss of use, data, or profits; or business interruption) however caused
|
||||
and on any theory of liability, whether in contract, strict liability,
|
||||
or tort (including negligence or otherwise) arising in any way out of
|
||||
the use of this software, even if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
|
||||
#include "opencv2/ximgproc/segmentation.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc::segmentation;
|
||||
|
||||
Scalar hsv_to_rgb(Scalar);
|
||||
Scalar color_mapping(int);
|
||||
|
||||
static void help() {
|
||||
std::cout << std::endl <<
|
||||
"A program demonstrating the use and capabilities of a particular graph based image" << std::endl <<
|
||||
"segmentation algorithm described in P. Felzenszwalb, D. Huttenlocher," << std::endl <<
|
||||
" \"Efficient Graph-Based Image Segmentation\"" << std::endl <<
|
||||
"International Journal of Computer Vision, Vol. 59, No. 2, September 2004" << std::endl << std::endl <<
|
||||
"Usage:" << std::endl <<
|
||||
"./graphsegmentation_demo input_image output_image [simga=0.5] [k=300] [min_size=100]" << std::endl;
|
||||
}
|
||||
|
||||
Scalar hsv_to_rgb(Scalar c) {
|
||||
Mat in(1, 1, CV_32FC3);
|
||||
Mat out(1, 1, CV_32FC3);
|
||||
|
||||
float * p = in.ptr<float>(0);
|
||||
|
||||
p[0] = (float)c[0] * 360.0f;
|
||||
p[1] = (float)c[1];
|
||||
p[2] = (float)c[2];
|
||||
|
||||
cvtColor(in, out, COLOR_HSV2RGB);
|
||||
|
||||
Scalar t;
|
||||
|
||||
Vec3f p2 = out.at<Vec3f>(0, 0);
|
||||
|
||||
t[0] = (int)(p2[0] * 255);
|
||||
t[1] = (int)(p2[1] * 255);
|
||||
t[2] = (int)(p2[2] * 255);
|
||||
|
||||
return t;
|
||||
|
||||
}
|
||||
|
||||
Scalar color_mapping(int segment_id) {
|
||||
|
||||
double base = (double)(segment_id) * 0.618033988749895 + 0.24443434;
|
||||
|
||||
return hsv_to_rgb(Scalar(fmod(base, 1.2), 0.95, 0.80));
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
if (argc < 2 || argc > 6) {
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
|
||||
Ptr<GraphSegmentation> gs = createGraphSegmentation();
|
||||
|
||||
if (argc > 3)
|
||||
gs->setSigma(atof(argv[3]));
|
||||
|
||||
if (argc > 4)
|
||||
gs->setK((float)atoi(argv[4]));
|
||||
|
||||
if (argc > 5)
|
||||
gs->setMinSize(atoi(argv[5]));
|
||||
|
||||
if (!gs) {
|
||||
std::cerr << "Failed to create GraphSegmentation Algorithm." << std::endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
Mat input, output, output_image;
|
||||
|
||||
input = imread(argv[1]);
|
||||
|
||||
if (!input.data) {
|
||||
std::cerr << "Failed to load input image" << std::endl;
|
||||
return -3;
|
||||
}
|
||||
|
||||
gs->processImage(input, output);
|
||||
|
||||
double min, max;
|
||||
minMaxLoc(output, &min, &max);
|
||||
|
||||
int nb_segs = (int)max + 1;
|
||||
|
||||
std::cout << nb_segs << " segments" << std::endl;
|
||||
|
||||
output_image = Mat::zeros(output.rows, output.cols, CV_8UC3);
|
||||
|
||||
uint* p;
|
||||
uchar* p2;
|
||||
|
||||
for (int i = 0; i < output.rows; i++) {
|
||||
|
||||
p = output.ptr<uint>(i);
|
||||
p2 = output_image.ptr<uchar>(i);
|
||||
|
||||
for (int j = 0; j < output.cols; j++) {
|
||||
Scalar color = color_mapping(p[j]);
|
||||
p2[j*3] = (uchar)color[0];
|
||||
p2[j*3 + 1] = (uchar)color[1];
|
||||
p2[j*3 + 2] = (uchar)color[2];
|
||||
}
|
||||
}
|
||||
|
||||
imwrite(argv[2], output_image);
|
||||
|
||||
std::cout << "Image written to " << argv[2] << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* By downloading, copying, installing or using the software you agree to this license.
|
||||
* If you do not agree to this license, do not download, install,
|
||||
* copy or use the software.
|
||||
*
|
||||
*
|
||||
* License Agreement
|
||||
* For Open Source Computer Vision Library
|
||||
* (3 - clause BSD License)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met :
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and / or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the names of the copyright holders nor the names of the contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* This software is provided by the copyright holders and contributors "as is" and
|
||||
* any express or implied warranties, including, but not limited to, the implied
|
||||
* warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
* In no event shall copyright holders or contributors be liable for any direct,
|
||||
* indirect, incidental, special, exemplary, or consequential damages
|
||||
* (including, but not limited to, procurement of substitute goods or services;
|
||||
* loss of use, data, or profits; or business interruption) however caused
|
||||
* and on any theory of liability, whether in contract, strict liability,
|
||||
* or tort(including negligence or otherwise) arising in any way out of
|
||||
* the use of this software, even if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
typedef void(*FilteringOperation)(const Mat& src, Mat& dst);
|
||||
//current mode (filtering operation example)
|
||||
FilteringOperation g_filterOp = NULL;
|
||||
|
||||
//list of filtering operations
|
||||
void filterDoNothing(const Mat& frame, Mat& dst);
|
||||
void filterBlurring(const Mat& frame, Mat& dst);
|
||||
void filterStylize(const Mat& frame, Mat& dst);
|
||||
void filterDetailEnhancement(const Mat& frame8u, Mat& dst);
|
||||
|
||||
//common sliders for every mode
|
||||
int g_sigmaColor = 25;
|
||||
int g_sigmaSpatial = 10;
|
||||
|
||||
//for Stylizing mode
|
||||
int g_edgesGamma = 100;
|
||||
|
||||
//for Details Enhancement mode
|
||||
int g_contrastBase = 100;
|
||||
int g_detailsLevel = 100;
|
||||
|
||||
int g_numberOfCPUs = cv::getNumberOfCPUs();
|
||||
|
||||
//We will use two callbacks to change parameters
|
||||
void changeModeCallback(int state, void *filter);
|
||||
void changeNumberOfCpuCallback(int count, void*);
|
||||
|
||||
void splitScreen(const Mat& rawFrame, Mat& outputFrame, Mat& srcFrame, Mat& processedFrame);
|
||||
|
||||
//trivial filter
|
||||
void filterDoNothing(const Mat& frame, Mat& dst)
|
||||
{
|
||||
frame.copyTo(dst);
|
||||
}
|
||||
|
||||
//simple edge-aware blurring
|
||||
void filterBlurring(const Mat& frame, Mat& dst)
|
||||
{
|
||||
dtFilter(frame, frame, dst, g_sigmaSpatial, g_sigmaColor, DTF_RF);
|
||||
}
|
||||
|
||||
//stylizing filter
|
||||
void filterStylize(const Mat& frame, Mat& dst)
|
||||
{
|
||||
//blur frame
|
||||
Mat filtered;
|
||||
dtFilter(frame, frame, filtered, g_sigmaSpatial, g_sigmaColor, DTF_NC);
|
||||
|
||||
//compute grayscale blurred frame
|
||||
Mat filteredGray;
|
||||
cvtColor(filtered, filteredGray, COLOR_BGR2GRAY);
|
||||
|
||||
//find gradients of blurred image
|
||||
Mat gradX, gradY;
|
||||
Sobel(filteredGray, gradX, CV_32F, 1, 0, 3, 1.0/255);
|
||||
Sobel(filteredGray, gradY, CV_32F, 0, 1, 3, 1.0/255);
|
||||
|
||||
//compute magnitude of gradient and fit it accordingly the gamma parameter
|
||||
Mat gradMagnitude;
|
||||
magnitude(gradX, gradY, gradMagnitude);
|
||||
cv::pow(gradMagnitude, g_edgesGamma/100.0, gradMagnitude);
|
||||
|
||||
//multiply a blurred frame to the value inversely proportional to the magnitude
|
||||
Mat multiplier = 1.0/(1.0 + gradMagnitude);
|
||||
cvtColor(multiplier, multiplier, COLOR_GRAY2BGR);
|
||||
multiply(filtered, multiplier, dst, 1, dst.type());
|
||||
}
|
||||
|
||||
void filterDetailEnhancement(const Mat& frame8u, Mat& dst)
|
||||
{
|
||||
Mat frame;
|
||||
frame8u.convertTo(frame, CV_32F, 1.0/255);
|
||||
|
||||
//Decompose image to 3 Lab channels
|
||||
Mat frameLab, frameLabCn[3];
|
||||
cvtColor(frame, frameLab, COLOR_BGR2Lab);
|
||||
split(frameLab, frameLabCn);
|
||||
|
||||
//Generate progressively smoother versions of the lightness channel
|
||||
Mat layer0 = frameLabCn[0]; //first channel is original lightness
|
||||
Mat layer1, layer2;
|
||||
dtFilter(layer0, layer0, layer1, g_sigmaSpatial, g_sigmaColor, DTF_IC);
|
||||
dtFilter(layer1, layer1, layer2, 2*g_sigmaSpatial, g_sigmaColor, DTF_IC);
|
||||
|
||||
//Compute detail layers
|
||||
Mat detailLayer1 = layer0 - layer1;
|
||||
Mat detailLayer2 = layer1 - layer2;
|
||||
|
||||
double cBase = g_contrastBase / 100.0;
|
||||
double cDetails1 = g_detailsLevel / 100.0;
|
||||
double cDetails2 = 2.0 - g_detailsLevel / 100.0;
|
||||
|
||||
//Generate lightness
|
||||
double meanLigtness = mean(frameLabCn[0])[0];
|
||||
frameLabCn[0] = cBase*(layer2 - meanLigtness) + meanLigtness; //fit contrast of base (most blurred) layer
|
||||
frameLabCn[0] += cDetails1*detailLayer1; //add weighted sum of detail layers to new lightness
|
||||
frameLabCn[0] += cDetails2*detailLayer2; //
|
||||
|
||||
//Update new lightness
|
||||
merge(frameLabCn, 3, frameLab);
|
||||
cvtColor(frameLab, frame, COLOR_Lab2BGR);
|
||||
frame.convertTo(dst, CV_8U, 255);
|
||||
}
|
||||
|
||||
void changeModeCallback(int state, void *filter)
|
||||
{
|
||||
if (state == 1)
|
||||
g_filterOp = (FilteringOperation) filter;
|
||||
}
|
||||
|
||||
void changeNumberOfCpuCallback(int count, void*)
|
||||
{
|
||||
count = std::max(1, count);
|
||||
g_numberOfCPUs = count;
|
||||
}
|
||||
|
||||
//divide screen on two parts: srcFrame and processed Frame
|
||||
void splitScreen(const Mat& rawFrame, Mat& outputFrame, Mat& srcFrame, Mat& processedFrame)
|
||||
{
|
||||
int h = rawFrame.rows;
|
||||
int w = rawFrame.cols;
|
||||
int cn = rawFrame.channels();
|
||||
|
||||
outputFrame.create(h, 2 * w, CV_MAKE_TYPE(CV_8U, cn));
|
||||
srcFrame = outputFrame(Range::all(), Range(0, w));
|
||||
processedFrame = outputFrame(Range::all(), Range(w, 2 * w));
|
||||
rawFrame.convertTo(srcFrame, srcFrame.type());
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
VideoCapture cap(0);
|
||||
if (!cap.isOpened())
|
||||
{
|
||||
cerr << "Capture device was not found" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
namedWindow("Demo");
|
||||
displayOverlay("Demo", "Press Ctrl+P to show property window", 5000);
|
||||
|
||||
//Thread trackbar
|
||||
createTrackbar("Threads", String(), &g_numberOfCPUs, cv::getNumberOfCPUs(), changeNumberOfCpuCallback);
|
||||
|
||||
//Buttons to choose different modes
|
||||
createButton("Mode Details Enhancement", changeModeCallback, (void*)filterDetailEnhancement, QT_RADIOBOX, true);
|
||||
createButton("Mode Stylizing", changeModeCallback, (void*)filterStylize, QT_RADIOBOX, false);
|
||||
createButton("Mode Blurring", changeModeCallback, (void*)filterBlurring, QT_RADIOBOX, false);
|
||||
createButton("Mode DoNothing", changeModeCallback, (void*)filterDoNothing, QT_RADIOBOX, false);
|
||||
|
||||
//sliders for Details Enhancement mode
|
||||
g_filterOp = filterDetailEnhancement; //set Details Enhancement as default filter
|
||||
createTrackbar("Detail contrast", String(), &g_contrastBase, 200);
|
||||
createTrackbar("Detail level" , String(), &g_detailsLevel, 200);
|
||||
|
||||
//sliders for Stylizing mode
|
||||
createTrackbar("Style gamma", String(), &g_edgesGamma, 300);
|
||||
|
||||
//sliders for every mode
|
||||
createTrackbar("Sigma Spatial", String(), &g_sigmaSpatial, 200);
|
||||
createTrackbar("Sigma Color" , String(), &g_sigmaColor, 200);
|
||||
|
||||
Mat rawFrame, outputFrame;
|
||||
Mat srcFrame, processedFrame;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
do
|
||||
{
|
||||
cap >> rawFrame;
|
||||
} while (rawFrame.empty());
|
||||
|
||||
cv::setNumThreads(g_numberOfCPUs); //speedup filtering
|
||||
|
||||
splitScreen(rawFrame, outputFrame, srcFrame, processedFrame);
|
||||
g_filterOp(srcFrame, processedFrame);
|
||||
|
||||
imshow("Demo", outputFrame);
|
||||
|
||||
if (waitKey(1) == 27) break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* C++ sample to demonstrate Niblack thresholding.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/ximgproc.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
|
||||
Mat_<uchar> src;
|
||||
int k_ = 8;
|
||||
int blockSize_ = 11;
|
||||
int type_ = THRESH_BINARY;
|
||||
int method_ = BINARIZATION_NIBLACK;
|
||||
|
||||
void on_trackbar(int, void*);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// read gray-scale image
|
||||
if(argc != 2)
|
||||
{
|
||||
cout << "Usage: ./niblack_thresholding [IMAGE]\n";
|
||||
return 1;
|
||||
}
|
||||
const char* filename = argv[1];
|
||||
src = imread(filename, IMREAD_GRAYSCALE);
|
||||
imshow("Source", src);
|
||||
|
||||
namedWindow("Niblack", WINDOW_AUTOSIZE);
|
||||
createTrackbar("k", "Niblack", &k_, 20, on_trackbar);
|
||||
createTrackbar("blockSize", "Niblack", &blockSize_, 30, on_trackbar);
|
||||
createTrackbar("method", "Niblack", &method_, 3, on_trackbar);
|
||||
createTrackbar("threshType", "Niblack", &type_, 4, on_trackbar);
|
||||
on_trackbar(0, 0);
|
||||
waitKey(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void on_trackbar(int, void*)
|
||||
{
|
||||
double k = static_cast<double>(k_-10)/10; // [-1.0, 1.0]
|
||||
int blockSize = 2*(blockSize_ >= 1 ? blockSize_ : 1) + 1; // 3,5,7,...,61
|
||||
int type = type_; // THRESH_BINARY, THRESH_BINARY_INV,
|
||||
// THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV
|
||||
int method = method_; //BINARIZATION_NIBLACK, BINARIZATION_SAUVOLA, BINARIZATION_WOLF, BINARIZATION_NICK
|
||||
Mat dst;
|
||||
niBlackThreshold(src, dst, 255, type, blockSize, k, method);
|
||||
imshow("Niblack", dst);
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* By downloading, copying, installing or using the software you agree to this license.
|
||||
* If you do not agree to this license, do not download, install,
|
||||
* copy or use the software.
|
||||
*
|
||||
*
|
||||
* License Agreement
|
||||
* For Open Source Computer Vision Library
|
||||
* (3 - clause BSD License)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met :
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and / or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the names of the copyright holders nor the names of the contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* This software is provided by the copyright holders and contributors "as is" and
|
||||
* any express or implied warranties, including, but not limited to, the implied
|
||||
* warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
* In no event shall copyright holders or contributors be liable for any direct,
|
||||
* indirect, incidental, special, exemplary, or consequential damages
|
||||
* (including, but not limited to, procurement of substitute goods or services;
|
||||
* loss of use, data, or profits; or business interruption) however caused
|
||||
* and on any theory of liability, whether in contract, strict liability,
|
||||
* or tort(including negligence or otherwise) arising in any way out of
|
||||
* the use of this software, even if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
#include "opencv2/ximgproc/paillou_filter.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
int aa = 100, ww = 10;
|
||||
|
||||
const char* window_name = "Gradient Modulus";
|
||||
|
||||
static void DisplayImage(Mat x,string s)
|
||||
{
|
||||
vector<Mat> sx;
|
||||
split(x, sx);
|
||||
vector<double> minVal(3), maxVal(3);
|
||||
for (int i = 0; i < static_cast<int>(sx.size()); i++)
|
||||
{
|
||||
minMaxLoc(sx[i], &minVal[i], &maxVal[i]);
|
||||
}
|
||||
maxVal[0] = *max_element(maxVal.begin(), maxVal.end());
|
||||
minVal[0] = *min_element(minVal.begin(), minVal.end());
|
||||
Mat uc;
|
||||
x.convertTo(uc, CV_8U,255/(maxVal[0]-minVal[0]),-255*minVal[0]/(maxVal[0]-minVal[0]));
|
||||
imshow(s, uc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function paillouFilter
|
||||
* @brief Trackbar callback
|
||||
*/
|
||||
static void PaillouFilter(int, void*pm)
|
||||
{
|
||||
Mat img = *((Mat*)pm);
|
||||
Mat dst;
|
||||
double a=aa/100.0, w=ww/100.0;
|
||||
Mat rx,ry;
|
||||
GradientPaillouX(img, rx, a, w);
|
||||
GradientPaillouY(img, ry, a, w);
|
||||
DisplayImage(rx, "Gx");
|
||||
DisplayImage(ry, "Gy");
|
||||
add(rx.mul(rx), ry.mul(ry), dst);
|
||||
sqrt(dst, dst);
|
||||
DisplayImage(dst, window_name );
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
cout << "usage: paillou_demo [image]" << endl;
|
||||
return 1;
|
||||
}
|
||||
Mat img = imread(argv[1]);
|
||||
if (img.empty())
|
||||
{
|
||||
cout << "File not found or empty image\n";
|
||||
return 1;
|
||||
}
|
||||
imshow("Original",img);
|
||||
namedWindow( window_name, WINDOW_AUTOSIZE );
|
||||
|
||||
/// Create a Trackbar for user to enter threshold
|
||||
createTrackbar( "a:",window_name, &aa, 400, PaillouFilter, &img );
|
||||
createTrackbar( "w:", window_name, &ww, 400, PaillouFilter, &img );
|
||||
PaillouFilter(0, &img);
|
||||
waitKey();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
static inline cv::Mat operator& ( const cv::Mat& lhs, const cv::Matx23d& rhs )
|
||||
{
|
||||
cv::Mat ret;
|
||||
cv::warpAffine ( lhs, ret, rhs, lhs.size(), cv::INTER_LINEAR );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline cv::Mat operator& ( const cv::Matx23d& lhs, const cv::Mat& rhs )
|
||||
{
|
||||
cv::Mat ret;
|
||||
cv::warpAffine ( rhs, ret, lhs, rhs.size(), cv::INTER_LINEAR | cv::WARP_INVERSE_MAP );
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
cv::CommandLineParser parser(argc, argv, "{ @input1 | ../data/peilin_plane.png | }{ @input2 | ../data/peilin_shape.png | }");
|
||||
parser.about("\nThis program demonstrates Pei&Lin Normalization\n");
|
||||
parser.printMessage();
|
||||
|
||||
std::string filename1 = parser.get<std::string>("@input1");
|
||||
std::string filename2 = parser.get<std::string>("@input2");
|
||||
|
||||
cv::Mat I = cv::imread(filename1, 0);
|
||||
if (I.empty())
|
||||
{
|
||||
std::cout << "Couldn't open image " << filename1 << std::endl;
|
||||
return 0;
|
||||
}
|
||||
cv::Mat J = cv::imread(filename2, 0);
|
||||
if (J.empty())
|
||||
{
|
||||
std::cout << "Couldn't open image " << filename2 << std::endl;
|
||||
return 0;
|
||||
}
|
||||
cv::Mat N = I & cv::ximgproc::PeiLinNormalization ( I );
|
||||
cv::Mat D = cv::ximgproc::PeiLinNormalization ( J ) & I;
|
||||
cv::imshow ( "I", I );
|
||||
cv::imshow ( "N", N );
|
||||
cv::imshow ( "J", J );
|
||||
cv::imshow ( "D", D );
|
||||
cv::waitKey();
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 662 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,18 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/ximgproc/radon_transform.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
int main() {
|
||||
Mat src = imread("peilin_plane.png", IMREAD_GRAYSCALE);
|
||||
Mat radon;
|
||||
ximgproc::RadonTransform(src, radon, 1, 0, 180, false, true);
|
||||
imshow("src image", src);
|
||||
imshow("Radon transform", radon);
|
||||
waitKey();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# This file is part of OpenCV project.
|
||||
# It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
# of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
if __name__ == "__main__":
|
||||
src = cv.imread("peilin_plane.png", cv.IMREAD_GRAYSCALE)
|
||||
radon = cv.ximgproc.RadonTransform(src).astype(np.float32)
|
||||
cv.imshow("src image", src)
|
||||
cv.imshow("Radon transform", radon)
|
||||
cv.waitKey()
|
||||
@@ -0,0 +1,246 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/ximgproc.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
|
||||
// Adapted from cv_timer in cv_utilities
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
Timer() : start_(0), time_(0) {}
|
||||
|
||||
void start()
|
||||
{
|
||||
start_ = cv::getTickCount();
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
CV_Assert(start_ != 0);
|
||||
int64 end = cv::getTickCount();
|
||||
time_ += end - start_;
|
||||
start_ = 0;
|
||||
}
|
||||
|
||||
double time()
|
||||
{
|
||||
double ret = time_ / cv::getTickFrequency();
|
||||
time_ = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
int64 start_, time_;
|
||||
};
|
||||
|
||||
static void help()
|
||||
{
|
||||
|
||||
printf("\nAllows to estimate the efficiency of the morphology operations implemented\n"
|
||||
"in ximgproc/run_length_morphology.cpp\n"
|
||||
"Call:\n example_ximgproc_run_length_morphology_demo [image] -u=factor_upscaling image\n"
|
||||
"Similar to the morphology2 sample of the main opencv library it shows the use\n"
|
||||
"of rect, ellipse and cross kernels\n\n"
|
||||
"As rectangular and cross-shaped structuring elements are highly optimized in opencv_imgproc module,\n"
|
||||
"only with elliptical structuring elements a speedup is possible (e.g. for larger circles).\n"
|
||||
"Run-length morphology has advantages for larger images.\n"
|
||||
"You can verify this by upscaling your input with e.g. -u=2\n");
|
||||
printf( "Hot keys: \n"
|
||||
"\tESC - quit the program\n"
|
||||
"\tr - use rectangle structuring element\n"
|
||||
"\te - use elliptic structuring element\n"
|
||||
"\tc - use cross-shaped structuring element\n"
|
||||
"\tSPACE - loop through all the options\n" );
|
||||
}
|
||||
|
||||
static void print_introduction()
|
||||
{
|
||||
printf("\nFirst select a threshold for binarization.\n"
|
||||
"Then move the sliders for erosion/dilation or open/close operation\n\n"
|
||||
"The ratio between the time of the execution from opencv_imgproc\n"
|
||||
"and the code using run-length encoding will be displayed in the console\n\n");
|
||||
}
|
||||
|
||||
Mat src, dst;
|
||||
|
||||
int element_shape = MORPH_ELLIPSE;
|
||||
|
||||
//the address of variable which receives trackbar position update
|
||||
int max_size = 40;
|
||||
int open_close_pos = 0;
|
||||
int erode_dilate_pos = 0;
|
||||
int nThreshold = 100;
|
||||
cv::Mat binaryImage;
|
||||
cv::Mat binaryRLE, dstRLE;
|
||||
cv::Mat rlePainted;
|
||||
|
||||
static void PaintRLEToImage(cv::Mat& rleImage, cv::Mat& res, unsigned char uValue)
|
||||
{
|
||||
res = cv::Scalar(0);
|
||||
rl::paint(res, rleImage, Scalar((double) uValue));
|
||||
}
|
||||
|
||||
|
||||
static bool AreImagesIdentical(cv::Mat& image1, cv::Mat& image2)
|
||||
{
|
||||
cv::Mat diff;
|
||||
cv::absdiff(image1, image2, diff);
|
||||
int nDiff = cv::countNonZero(diff);
|
||||
return (nDiff == 0);
|
||||
}
|
||||
|
||||
// callback function for open/close trackbar
|
||||
static void OpenClose(int, void*)
|
||||
{
|
||||
int n = open_close_pos - max_size;
|
||||
int an = n > 0 ? n : -n;
|
||||
Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an) );
|
||||
Timer timer;
|
||||
timer.start();
|
||||
if( n < 0 )
|
||||
morphologyEx(binaryImage, dst, MORPH_OPEN, element);
|
||||
else
|
||||
morphologyEx(binaryImage, dst, MORPH_CLOSE, element);
|
||||
timer.stop();
|
||||
double imgproc_duration = timer.time();
|
||||
|
||||
element = rl::getStructuringElement(element_shape, Size(an * 2 + 1, an * 2 + 1));
|
||||
|
||||
Timer timer2;
|
||||
timer2.start();
|
||||
if (n < 0)
|
||||
rl::morphologyEx(binaryRLE, dstRLE, MORPH_OPEN, element, true);
|
||||
else
|
||||
rl::morphologyEx(binaryRLE, dstRLE, MORPH_CLOSE, element, true);
|
||||
|
||||
timer2.stop();
|
||||
double rl_duration = timer2.time();
|
||||
cout << "ratio open/close duration: " << rl_duration / imgproc_duration << " (run-length: "
|
||||
<< rl_duration << ", pixelwise: " << imgproc_duration << " )" << std::endl;
|
||||
|
||||
PaintRLEToImage(dstRLE, rlePainted, (unsigned char)255);
|
||||
if (!AreImagesIdentical(dst, rlePainted))
|
||||
{
|
||||
cout << "error result image are not identical" << endl;
|
||||
}
|
||||
|
||||
imshow("Open/Close", rlePainted);
|
||||
}
|
||||
|
||||
// callback function for erode/dilate trackbar
|
||||
static void ErodeDilate(int, void*)
|
||||
{
|
||||
int n = erode_dilate_pos - max_size;
|
||||
int an = n > 0 ? n : -n;
|
||||
Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an) );
|
||||
Timer timer;
|
||||
timer.start();
|
||||
if( n < 0 )
|
||||
erode(binaryImage, dst, element);
|
||||
else
|
||||
dilate(binaryImage, dst, element);
|
||||
timer.stop();
|
||||
double imgproc_duration = timer.time();
|
||||
|
||||
element = rl::getStructuringElement(element_shape, Size(an*2+1, an*2+1));
|
||||
|
||||
Timer timer2;
|
||||
timer2.start();
|
||||
if( n < 0 )
|
||||
rl::erode(binaryRLE, dstRLE, element, true);
|
||||
else
|
||||
rl::dilate(binaryRLE, dstRLE, element);
|
||||
timer2.stop();
|
||||
double rl_duration = timer2.time();
|
||||
|
||||
PaintRLEToImage(dstRLE, rlePainted, (unsigned char)255);
|
||||
cout << "ratio erode/dilate duration: " << rl_duration / imgproc_duration <<
|
||||
" (run-length: " << rl_duration << ", pixelwise: " << imgproc_duration << " )" << std::endl;
|
||||
|
||||
if (!AreImagesIdentical(dst, rlePainted))
|
||||
{
|
||||
cout << "error result image are not identical" << endl;
|
||||
}
|
||||
|
||||
imshow("Erode/Dilate", rlePainted);
|
||||
}
|
||||
|
||||
static void OnChangeThreshold(int, void*)
|
||||
{
|
||||
threshold(src, binaryImage, (double) nThreshold, 255.0, THRESH_BINARY );
|
||||
rl::threshold(src, binaryRLE, (double) nThreshold, THRESH_BINARY);
|
||||
imshow("Threshold", binaryImage);
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
cv::CommandLineParser parser(argc, argv, "{help h||}{ @image | ../data/aloeL.jpg | }{u| |}");
|
||||
if (parser.has("help"))
|
||||
{
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
std::string filename = parser.get<std::string>("@image");
|
||||
|
||||
cv::Mat srcIn;
|
||||
if( (srcIn = imread(filename,IMREAD_GRAYSCALE)).empty() )
|
||||
{
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
int nScale = 1;
|
||||
if (parser.has("u"))
|
||||
{
|
||||
int theScale = parser.get<int>("u");
|
||||
if (theScale > 1)
|
||||
nScale = theScale;
|
||||
}
|
||||
|
||||
if (nScale == 1)
|
||||
src = srcIn;
|
||||
else
|
||||
cv::resize(srcIn, src, cv::Size(srcIn.rows * nScale, srcIn.cols * nScale));
|
||||
|
||||
cout << "scale factor read " << nScale << endl;
|
||||
|
||||
print_introduction();
|
||||
|
||||
//create windows for output images
|
||||
namedWindow("Open/Close",1);
|
||||
namedWindow("Erode/Dilate",1);
|
||||
namedWindow("Threshold",1);
|
||||
|
||||
open_close_pos = erode_dilate_pos = max_size - 10;
|
||||
createTrackbar("size s.e.", "Open/Close",&open_close_pos,max_size*2+1,OpenClose);
|
||||
createTrackbar("size s.e.", "Erode/Dilate",&erode_dilate_pos,max_size*2+1,ErodeDilate);
|
||||
createTrackbar("threshold", "Threshold",&nThreshold,255, OnChangeThreshold);
|
||||
OnChangeThreshold(0, 0);
|
||||
rlePainted.create(cv::Size(src.cols, src.rows), CV_8UC1);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
OpenClose(open_close_pos, 0);
|
||||
ErodeDilate(erode_dilate_pos, 0);
|
||||
char c = (char)waitKey(0);
|
||||
|
||||
if( c == 27 )
|
||||
break;
|
||||
if( c == 'e' )
|
||||
element_shape = MORPH_ELLIPSE;
|
||||
else if( c == 'r' )
|
||||
element_shape = MORPH_RECT;
|
||||
else if( c == 'c' )
|
||||
element_shape = MORPH_CROSS;
|
||||
else if( c == ' ' )
|
||||
element_shape = (element_shape + 1) % 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
using namespace std;
|
||||
|
||||
void trackbarChanged(int pos, void* data);
|
||||
|
||||
static void help()
|
||||
{
|
||||
cout << "\nThis program demonstrates SEEDS superpixels using OpenCV class SuperpixelSEEDS\n"
|
||||
"Use [space] to toggle output mode\n"
|
||||
"\n"
|
||||
"It captures either from the camera of your choice: 0, 1, ... default 0\n"
|
||||
"Or from an input image\n"
|
||||
"Call:\n"
|
||||
"./seeds [camera #, default 0]\n"
|
||||
"./seeds [input image file]\n" << endl;
|
||||
}
|
||||
|
||||
static const char* window_name = "SEEDS Superpixels";
|
||||
|
||||
static bool init = false;
|
||||
|
||||
void trackbarChanged(int, void*)
|
||||
{
|
||||
init = false;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
VideoCapture cap;
|
||||
Mat input_image;
|
||||
bool use_video_capture = false;
|
||||
help();
|
||||
|
||||
if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])) )
|
||||
{
|
||||
cap.open(argc == 2 ? argv[1][0] - '0' : 0);
|
||||
use_video_capture = true;
|
||||
}
|
||||
else if( argc >= 2 )
|
||||
{
|
||||
input_image = imread(argv[1]);
|
||||
}
|
||||
|
||||
if( use_video_capture )
|
||||
{
|
||||
if( !cap.isOpened() )
|
||||
{
|
||||
cout << "Could not initialize capturing...\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if( input_image.empty() )
|
||||
{
|
||||
cout << "Could not open image...\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
namedWindow(window_name, 0);
|
||||
int num_iterations = 4;
|
||||
int prior = 2;
|
||||
bool double_step = false;
|
||||
int num_superpixels = 400;
|
||||
int num_levels = 4;
|
||||
int num_histogram_bins = 5;
|
||||
createTrackbar("Number of Superpixels", window_name, &num_superpixels, 1000, trackbarChanged);
|
||||
createTrackbar("Smoothing Prior", window_name, &prior, 5, trackbarChanged);
|
||||
createTrackbar("Number of Levels", window_name, &num_levels, 10, trackbarChanged);
|
||||
createTrackbar("Iterations", window_name, &num_iterations, 12, 0);
|
||||
|
||||
Mat result, mask;
|
||||
Ptr<SuperpixelSEEDS> seeds;
|
||||
int width, height;
|
||||
int display_mode = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Mat frame;
|
||||
if( use_video_capture )
|
||||
cap >> frame;
|
||||
else
|
||||
input_image.copyTo(frame);
|
||||
|
||||
if( frame.empty() )
|
||||
break;
|
||||
|
||||
if( !init )
|
||||
{
|
||||
width = frame.size().width;
|
||||
height = frame.size().height;
|
||||
seeds = createSuperpixelSEEDS(width, height, frame.channels(), num_superpixels,
|
||||
num_levels, prior, num_histogram_bins, double_step);
|
||||
init = true;
|
||||
}
|
||||
Mat converted;
|
||||
cvtColor(frame, converted, COLOR_BGR2HSV);
|
||||
|
||||
double t = (double) getTickCount();
|
||||
|
||||
seeds->iterate(converted, num_iterations);
|
||||
result = frame;
|
||||
|
||||
t = ((double) getTickCount() - t) / getTickFrequency();
|
||||
printf("SEEDS segmentation took %i ms with %3i superpixels\n",
|
||||
(int) (t * 1000), seeds->getNumberOfSuperpixels());
|
||||
|
||||
/* retrieve the segmentation result */
|
||||
Mat labels;
|
||||
seeds->getLabels(labels);
|
||||
|
||||
/* get the contours for displaying */
|
||||
seeds->getLabelContourMask(mask, false);
|
||||
result.setTo(Scalar(0, 0, 255), mask);
|
||||
|
||||
/* display output */
|
||||
switch (display_mode)
|
||||
{
|
||||
case 0: //superpixel contours
|
||||
imshow(window_name, result);
|
||||
break;
|
||||
case 1: //mask
|
||||
imshow(window_name, mask);
|
||||
break;
|
||||
case 2: //labels array
|
||||
{
|
||||
// use the last x bit to determine the color. Note that this does not
|
||||
// guarantee that 2 neighboring superpixels have different colors.
|
||||
const int num_label_bits = 2;
|
||||
labels &= (1 << num_label_bits) - 1;
|
||||
labels *= 1 << (16 - num_label_bits);
|
||||
imshow(window_name, labels);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
int c = waitKey(1);
|
||||
if( (c & 255) == 'q' || c == 'Q' || (c & 255) == 27 )
|
||||
break;
|
||||
else if( (c & 255) == ' ' )
|
||||
display_mode = (display_mode + 1) % 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
By downloading, copying, installing or using the software you agree to this
|
||||
license. If you do not agree to this license, do not download, install,
|
||||
copy or use the software.
|
||||
License Agreement
|
||||
For Open Source Computer Vision Library
|
||||
(3-clause BSD License)
|
||||
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
Third party copyrights are property of their respective owners.
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of the contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
This software is provided by the copyright holders and contributors "as is" and
|
||||
any express or implied warranties, including, but not limited to, the implied
|
||||
warranties of merchantability and fitness for a particular purpose are
|
||||
disclaimed. In no event shall copyright holders or contributors be liable for
|
||||
any direct, indirect, incidental, special, exemplary, or consequential damages
|
||||
(including, but not limited to, procurement of substitute goods or services;
|
||||
loss of use, data, or profits; or business interruption) however caused
|
||||
and on any theory of liability, whether in contract, strict liability,
|
||||
or tort (including negligence or otherwise) arising in any way out of
|
||||
the use of this software, even if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
|
||||
#include "opencv2/ximgproc/segmentation.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc::segmentation;
|
||||
|
||||
static void help() {
|
||||
std::cout << std::endl <<
|
||||
"A program demonstrating the use and capabilities of a particular image segmentation algorithm described" << std::endl <<
|
||||
" in Jasper R. R. Uijlings, Koen E. A. van de Sande, Theo Gevers, Arnold W. M. Smeulders: " << std::endl <<
|
||||
" \"Selective Search for Object Recognition\"" << std::endl <<
|
||||
"International Journal of Computer Vision, Volume 104 (2), page 154-171, 2013" << std::endl << std::endl <<
|
||||
"Usage:" << std::endl <<
|
||||
"./selectivesearchsegmentation_demo input_image (single|fast|quality)" << std::endl <<
|
||||
"Use a to display less rects, d to display more rects, q to quit" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
if (argc < 3) {
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
|
||||
Mat img = imread(argv[1]);
|
||||
|
||||
Ptr<SelectiveSearchSegmentation> gs = createSelectiveSearchSegmentation();
|
||||
gs->setBaseImage(img);
|
||||
|
||||
if (argv[2][0] == 's') {
|
||||
gs->switchToSingleStrategy();
|
||||
} else if (argv[2][0] == 'f') {
|
||||
gs->switchToSelectiveSearchFast();
|
||||
} else if (argv[2][0] == 'q') {
|
||||
gs->switchToSelectiveSearchQuality();
|
||||
} else {
|
||||
help();
|
||||
return -2;
|
||||
}
|
||||
|
||||
std::vector<Rect> rects;
|
||||
gs->process(rects);
|
||||
|
||||
int nb_rects = 10;
|
||||
|
||||
char c = (char)waitKey();
|
||||
|
||||
while(c != 'q') {
|
||||
|
||||
Mat wimg = img.clone();
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(std::vector<Rect>::iterator it = rects.begin(); it != rects.end(); ++it) {
|
||||
if (i++ < nb_rects) {
|
||||
rectangle(wimg, *it, Scalar(0, 0, 255));
|
||||
}
|
||||
}
|
||||
|
||||
imshow("Output", wimg);
|
||||
c = (char)waitKey();
|
||||
|
||||
if (c == 'd') {
|
||||
nb_rects += 10;
|
||||
}
|
||||
|
||||
if (c == 'a' && nb_rects > 10) {
|
||||
nb_rects -= 10;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
A program demonstrating the use and capabilities of a particular image segmentation algorithm described
|
||||
in Jasper R. R. Uijlings, Koen E. A. van de Sande, Theo Gevers, Arnold W. M. Smeulders:
|
||||
"Selective Search for Object Recognition"
|
||||
International Journal of Computer Vision, Volume 104 (2), page 154-171, 2013
|
||||
Usage:
|
||||
./selectivesearchsegmentation_demo.py input_image (single|fast|quality)
|
||||
Use "a" to display less rects, 'd' to display more rects, "q" to quit.
|
||||
'''
|
||||
|
||||
import cv2 as cv
|
||||
import sys
|
||||
|
||||
if __name__ == '__main__':
|
||||
img = cv.imread(sys.argv[1])
|
||||
|
||||
cv.setUseOptimized(True)
|
||||
cv.setNumThreads(8)
|
||||
|
||||
gs = cv.ximgproc.segmentation.createSelectiveSearchSegmentation()
|
||||
gs.setBaseImage(img)
|
||||
|
||||
if (sys.argv[2][0] == 's'):
|
||||
gs.switchToSingleStrategy()
|
||||
|
||||
elif (sys.argv[2][0] == 'f'):
|
||||
gs.switchToSelectiveSearchFast()
|
||||
|
||||
elif (sys.argv[2][0] == 'q'):
|
||||
gs.switchToSelectiveSearchQuality()
|
||||
else:
|
||||
print(__doc__)
|
||||
sys.exit(1)
|
||||
|
||||
rects = gs.process()
|
||||
nb_rects = 10
|
||||
|
||||
while True:
|
||||
wimg = img.copy()
|
||||
|
||||
for i in range(len(rects)):
|
||||
if (i < nb_rects):
|
||||
x, y, w, h = rects[i]
|
||||
cv.rectangle(wimg, (x, y), (x+w, y+h), (0, 255, 0), 1, cv.LINE_AA)
|
||||
|
||||
cv.imshow("Output", wimg);
|
||||
c = cv.waitKey()
|
||||
|
||||
if (c == 100):
|
||||
nb_rects += 10
|
||||
|
||||
elif (c == 97 and nb_rects > 10):
|
||||
nb_rects -= 10
|
||||
|
||||
elif (c == 113):
|
||||
break
|
||||
|
||||
cv.destroyAllWindows()
|
||||
@@ -0,0 +1,138 @@
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
using namespace std;
|
||||
|
||||
static const char* window_name = "SLIC Superpixels";
|
||||
|
||||
static const char* keys =
|
||||
"{h help | | help menu}"
|
||||
"{c camera |0| camera id}"
|
||||
"{i image | | image file}"
|
||||
"{a algorithm |1| SLIC(0),SLICO(1),MSLIC(2)}"
|
||||
;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
CommandLineParser cmd(argc,argv,keys);
|
||||
if (cmd.has("help")) {
|
||||
cmd.about("This program demonstrates SLIC superpixels using OpenCV class SuperpixelSLIC.\n"
|
||||
"If no image file is supplied, try to open a webcam.\n"
|
||||
"Use [space] to toggle output mode, ['q' or 'Q' or 'esc'] to exit.\n");
|
||||
cmd.printMessage();
|
||||
return 0;
|
||||
}
|
||||
int capture = cmd.get<int>("camera");
|
||||
String img_file = cmd.get<String>("image");
|
||||
int algorithm = cmd.get<int>("algorithm");
|
||||
int region_size = 50;
|
||||
int ruler = 30;
|
||||
int min_element_size = 50;
|
||||
int num_iterations = 3;
|
||||
bool use_video_capture = img_file.empty();
|
||||
|
||||
VideoCapture cap;
|
||||
Mat input_image;
|
||||
|
||||
if( use_video_capture )
|
||||
{
|
||||
if( !cap.open(capture) )
|
||||
{
|
||||
cout << "Could not initialize capturing..."<<capture<<"\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
input_image = imread(img_file);
|
||||
if( input_image.empty() )
|
||||
{
|
||||
cout << "Could not open image..."<<img_file<<"\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
namedWindow(window_name, 0);
|
||||
createTrackbar("Algorithm", window_name, &algorithm, 2, 0);
|
||||
createTrackbar("Region size", window_name, ®ion_size, 200, 0);
|
||||
createTrackbar("Ruler", window_name, &ruler, 100, 0);
|
||||
createTrackbar("Connectivity", window_name, &min_element_size, 100, 0);
|
||||
createTrackbar("Iterations", window_name, &num_iterations, 12, 0);
|
||||
|
||||
Mat result, mask;
|
||||
int display_mode = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Mat frame;
|
||||
if( use_video_capture )
|
||||
cap >> frame;
|
||||
else
|
||||
input_image.copyTo(frame);
|
||||
|
||||
if( frame.empty() )
|
||||
break;
|
||||
|
||||
result = frame;
|
||||
Mat converted;
|
||||
cvtColor(frame, converted, COLOR_BGR2HSV);
|
||||
|
||||
double t = (double) getTickCount();
|
||||
|
||||
Ptr<SuperpixelSLIC> slic = createSuperpixelSLIC(converted,algorithm+SLIC,region_size,float(ruler));
|
||||
slic->iterate(num_iterations);
|
||||
if (min_element_size>0)
|
||||
slic->enforceLabelConnectivity(min_element_size);
|
||||
|
||||
t = ((double) getTickCount() - t) / getTickFrequency();
|
||||
cout << "SLIC" << (algorithm?'O':' ')
|
||||
<< " segmentation took " << (int) (t * 1000)
|
||||
<< " ms with " << slic->getNumberOfSuperpixels() << " superpixels" << endl;
|
||||
|
||||
// get the contours for displaying
|
||||
slic->getLabelContourMask(mask, true);
|
||||
result.setTo(Scalar(0, 0, 255), mask);
|
||||
|
||||
// display output
|
||||
switch (display_mode)
|
||||
{
|
||||
case 0: //superpixel contours
|
||||
imshow(window_name, result);
|
||||
break;
|
||||
case 1: //mask
|
||||
imshow(window_name, mask);
|
||||
break;
|
||||
case 2: //labels array
|
||||
{
|
||||
// use the last x bit to determine the color. Note that this does not
|
||||
// guarantee that 2 neighboring superpixels have different colors.
|
||||
// retrieve the segmentation result
|
||||
Mat labels;
|
||||
slic->getLabels(labels);
|
||||
const int num_label_bits = 2;
|
||||
labels &= (1 << num_label_bits) - 1;
|
||||
labels *= 1 << (16 - num_label_bits);
|
||||
imshow(window_name, labels);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int c = waitKey(1) & 0xff;
|
||||
if( c == 'q' || c == 'Q' || c == 27 )
|
||||
break;
|
||||
else if( c == ' ' )
|
||||
display_mode = (display_mode + 1) % 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 872 KiB |
@@ -0,0 +1,96 @@
|
||||
/**************************************************************************************
|
||||
The structured forests for fast edge detection demo requires you to provide a model.
|
||||
This model can be found at the opencv_extra repository on Github on the following link:
|
||||
https://github.com/opencv/opencv_extra/blob/master/testdata/cv/ximgproc/model.yml.gz
|
||||
***************************************************************************************/
|
||||
|
||||
#include <opencv2/ximgproc.hpp>
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::ximgproc;
|
||||
|
||||
const char* keys =
|
||||
{
|
||||
"{i || input image file name}"
|
||||
"{m || model file name}"
|
||||
"{o || output image file name}"
|
||||
};
|
||||
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
CommandLineParser parser(argc, argv, keys);
|
||||
parser.about("This sample demonstrates usage of structured forests for fast edge detection");
|
||||
parser.printMessage();
|
||||
|
||||
if ( !parser.check() )
|
||||
{
|
||||
parser.printErrors();
|
||||
return -1;
|
||||
}
|
||||
|
||||
String modelFilename = parser.get<String>("m");
|
||||
String inFilename = parser.get<String>("i");
|
||||
String outFilename = parser.get<String>("o");
|
||||
|
||||
//! [imread]
|
||||
Mat image = imread(inFilename, IMREAD_COLOR);
|
||||
if ( image.empty() )
|
||||
CV_Error(Error::StsError, String("Cannot read image file: ") + inFilename);
|
||||
//! [imread]
|
||||
|
||||
if ( modelFilename.size() == 0)
|
||||
CV_Error(Error::StsError, String("Empty model name"));
|
||||
|
||||
//! [convert]
|
||||
image.convertTo(image, DataType<float>::type, 1/255.0);
|
||||
//! [convert]
|
||||
|
||||
TickMeter tm;
|
||||
tm.start();
|
||||
//! [create]
|
||||
Ptr<StructuredEdgeDetection> pDollar =
|
||||
createStructuredEdgeDetection(modelFilename);
|
||||
//! [create]
|
||||
|
||||
tm.stop();
|
||||
std::cout << "createStructuredEdgeDetection() time : " << tm << std::endl;
|
||||
|
||||
tm.reset();
|
||||
tm.start();
|
||||
//! [detect]
|
||||
Mat edges;
|
||||
pDollar->detectEdges(image, edges);
|
||||
//! [detect]
|
||||
tm.stop();
|
||||
std::cout << "detectEdges() time : " << tm << std::endl;
|
||||
|
||||
tm.reset();
|
||||
tm.start();
|
||||
//! [nms]
|
||||
// computes orientation from edge map
|
||||
Mat orientation_map;
|
||||
pDollar->computeOrientation(edges, orientation_map);
|
||||
|
||||
// suppress edges
|
||||
Mat edge_nms;
|
||||
pDollar->edgesNms(edges, orientation_map, edge_nms, 2, 0, 1, true);
|
||||
//! [nms]
|
||||
|
||||
tm.stop();
|
||||
std::cout << "nms time : " << tm << std::endl;
|
||||
|
||||
//! [imshow]
|
||||
if ( outFilename.size() == 0 )
|
||||
{
|
||||
imshow("edges", edges);
|
||||
imshow("edges nms", edge_nms);
|
||||
waitKey(0);
|
||||
}
|
||||
else
|
||||
imwrite(outFilename, 255*edges);
|
||||
//! [imshow]
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
#include "opencv2/ximgproc.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
int main()
|
||||
{
|
||||
Mat img = imread("opencv-logo.png", IMREAD_COLOR);
|
||||
resize(img, img, Size(), 0.5, 0.5, INTER_LINEAR_EXACT);
|
||||
|
||||
/// Threshold the input image
|
||||
Mat img_grayscale, img_binary;
|
||||
cvtColor(img, img_grayscale,COLOR_BGR2GRAY);
|
||||
threshold(img_grayscale, img_binary, 0, 255, THRESH_OTSU | THRESH_BINARY_INV);
|
||||
|
||||
/// Apply thinning to get a skeleton
|
||||
Mat img_thinning_ZS, img_thinning_GH;
|
||||
ximgproc::thinning(img_binary, img_thinning_ZS, ximgproc::THINNING_ZHANGSUEN);
|
||||
ximgproc::thinning(img_binary, img_thinning_GH, ximgproc::THINNING_GUOHALL);
|
||||
|
||||
/// Make 3 channel images from thinning result
|
||||
Mat result_ZS(img.rows, img.cols, CV_8UC3), result_GH(img.rows, img.cols, CV_8UC3);
|
||||
|
||||
Mat in[] = { img_thinning_ZS, img_thinning_ZS, img_thinning_ZS };
|
||||
Mat in2[] = { img_thinning_GH, img_thinning_GH, img_thinning_GH };
|
||||
int from_to[] = { 0,0, 1,1, 2,2 };
|
||||
mixChannels( in, 3, &result_ZS, 1, from_to, 3 );
|
||||
mixChannels( in2, 3, &result_GH, 1, from_to, 3 );
|
||||
|
||||
/// Combine everything into a canvas
|
||||
Mat canvas(img.rows, img.cols * 3, CV_8UC3);
|
||||
img.copyTo( canvas( Rect(0, 0, img.cols, img.rows) ) );
|
||||
result_ZS.copyTo( canvas( Rect(img.cols, 0, img.cols, img.rows) ) );
|
||||
result_GH.copyTo( canvas( Rect(img.cols*2, 0, img.cols, img.rows) ) );
|
||||
|
||||
/// Visualize result
|
||||
imshow("Skeleton", canvas); waitKey(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user