vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e

This commit is contained in:
Gitea Mirror Bot
2026-08-22 00:11:13 +08:00
commit 12022378a3
3872 changed files with 2513409 additions and 0 deletions
+9
View File
@@ -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;
}
+417
View File
@@ -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
+59
View File
@@ -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:])
+120
View File
@@ -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;
}
+151
View File
@@ -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;
}
+105
View File
@@ -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;
}
+46
View File
@@ -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)
+78
View File
@@ -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;
}
+231
View File
@@ -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);
}
+112
View File
@@ -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;
}
+50
View File
@@ -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;
}
+157
View File
@@ -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()
+138
View File
@@ -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, &region_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;
}
+45
View File
@@ -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;
}