├── .github ├── .gitignore └── workflows │ └── R-CMD-check.yaml ├── LICENSE ├── cleanup ├── man ├── figures │ └── logo.png ├── reexports.Rd ├── opencv-area.Rd ├── ocv_keypoints.Rd ├── qrcode.Rd └── opencv.Rd ├── tests ├── testthat │ ├── qrtest.jpg │ └── test-qr_code.R └── testthat.R ├── src ├── Makevars.in ├── version.cpp ├── color.cpp ├── util.hpp ├── points.cpp ├── opencv_types.h ├── effects.cpp ├── Makevars.win ├── hog.cpp ├── qrdetect.cpp ├── features.cpp ├── areas.cpp ├── face.cpp ├── enums.cpp ├── util.cpp ├── base.cpp └── RcppExports.cpp ├── .gitignore ├── .Rbuildignore ├── R ├── utils.R ├── face.R ├── xmldata.R ├── init.R ├── qr.R ├── areas.R ├── keypoints.R ├── opencv.R └── RcppExports.R ├── opencv.Rproj ├── NEWS ├── NAMESPACE ├── tools └── winlibs.R ├── LICENSE.md ├── DESCRIPTION ├── README.md └── configure /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2022 2 | COPYRIGHT HOLDER: Jeroen Ooms 3 | -------------------------------------------------------------------------------- /cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -f src/Makevars configure.log autobrew 3 | -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/opencv/HEAD/man/figures/logo.png -------------------------------------------------------------------------------- /tests/testthat/qrtest.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/opencv/HEAD/tests/testthat/qrtest.jpg -------------------------------------------------------------------------------- /src/Makevars.in: -------------------------------------------------------------------------------- 1 | PKG_CPPFLAGS=@cflags@ 2 | PKG_LIBS=@libs@ 3 | 4 | all: cleanup 5 | 6 | cleanup: $(SHLIB) 7 | @rm -Rf ../.deps 8 | -------------------------------------------------------------------------------- /src/version.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // [[Rcpp::export]] 5 | std::string cvversion(){ 6 | return CV_VERSION; 7 | } 8 | -------------------------------------------------------------------------------- /src/color.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | // [[Rcpp::export]] 4 | XPtrMat cvmat_grayscale(XPtrMat src){ 5 | cv::Mat output; 6 | cv::cvtColor(get_mat(src), output, cv::COLOR_BGR2GRAY); 7 | return cvmat_xptr(output); 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .Rproj.user 3 | .Rhistory 4 | .RData 5 | src/*.o 6 | src/*.so 7 | src/*.dll 8 | src/*.a 9 | src/*.def 10 | src/Makevars 11 | tools/option_table.txt 12 | inst/doc 13 | R/sysdata.rda 14 | windows 15 | configure.log 16 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^\.DS_Store$ 2 | ^\.travis.yml$ 3 | ^\.git$ 4 | ^\.gitignore$ 5 | ^\.Rhistory$ 6 | ^.*\.Rproj$ 7 | ^\.Rproj\.user$ 8 | ^windows$ 9 | ^src/Makevars$ 10 | ^appveyor\.yml$ 11 | ^LICENSE\.md$ 12 | ^README\.md$ 13 | ^configure.log$ 14 | ^.github$ 15 | ^\.github$ 16 | -------------------------------------------------------------------------------- /src/util.hpp: -------------------------------------------------------------------------------- 1 | #include "opencv_types.h" 2 | void detectAndDraw( cv::Mat img, cv::CascadeClassifier& cascade, 3 | cv::CascadeClassifier& nestedCascade, 4 | double scale, bool tryflip ); 5 | cv::Mat get_mat(XPtrMat image); 6 | XPtrMat cvmat_xptr(cv::Mat *frame); 7 | XPtrMat cvmat_xptr(cv::Mat orig); 8 | -------------------------------------------------------------------------------- /tests/testthat/test-qr_code.R: -------------------------------------------------------------------------------- 1 | test_that("qr scanner works", { 2 | skip_if(identical(Sys.info()[["sysname"]], 'Linux') && ocv_version() < "4.5.2") 3 | img <- ocv_read('qrtest.jpg') 4 | expect_s3_class(img, "opencv-image") 5 | txt <- ocv_qr_detect(img) 6 | outimg <- ocv_qr_detect(img, draw = TRUE) 7 | expect_s3_class(outimg, "opencv-image") 8 | expect_equal(c(txt), "https://www.r-project.org") 9 | }) 10 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | recoder <- function(x, from = c(), to = c()){ 2 | if(length(x) == 0){ 3 | return(x) 4 | } 5 | stopifnot(length(from) == length(to)) 6 | nongiven <- unique(x[!is.na(x)]) 7 | nongiven <- setdiff(nongiven, from) 8 | if(length(nongiven) > 0) { 9 | from <- append(x = from, values = nongiven) 10 | to <- append(x = to, values = nongiven) 11 | } 12 | to[match(x, from)] 13 | } 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview 7 | # * https://testthat.r-lib.org/articles/special-files.html 8 | 9 | library(testthat) 10 | library(opencv) 11 | 12 | test_check("opencv") 13 | -------------------------------------------------------------------------------- /man/reexports.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/opencv.R 3 | \docType{import} 4 | \name{reexports} 5 | \alias{reexports} 6 | \alias{\%>\%} 7 | \title{Objects exported from other packages} 8 | \keyword{internal} 9 | \description{ 10 | These objects are imported from other packages. Follow the links 11 | below to see their documentation. 12 | 13 | \describe{ 14 | \item{magrittr}{\code{\link[magrittr:pipe]{\%>\%}}} 15 | }} 16 | 17 | -------------------------------------------------------------------------------- /R/face.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @rdname opencv 3 | ocv_face <- function(image){ 4 | facedata <- find_data_xml('haarcascades/haarcascade_frontalface_alt.xml') 5 | eyedata <- find_data_xml('haarcascades/haarcascade_eye_tree_eyeglasses.xml') 6 | cvmat_face(image, facedata, eyedata) 7 | } 8 | 9 | #' @export 10 | #' @rdname opencv 11 | ocv_facemask <- function(image){ 12 | facedata <- find_data_xml('haarcascades/haarcascade_frontalface_alt.xml') 13 | cvmat_facemask(image, facedata) 14 | } 15 | 16 | -------------------------------------------------------------------------------- /opencv.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | ProjectId: 09cccc80-02ba-4f3c-8993-648895ae8da9 3 | 4 | RestoreWorkspace: Default 5 | SaveWorkspace: Default 6 | AlwaysSaveHistory: Default 7 | 8 | EnableCodeIndexing: Yes 9 | UseSpacesForTab: Yes 10 | NumSpacesForTab: 2 11 | Encoding: UTF-8 12 | 13 | RnwWeave: Sweave 14 | LaTeX: pdfLaTeX 15 | 16 | AutoAppendNewline: Yes 17 | StripTrailingWhitespace: Yes 18 | 19 | BuildType: Package 20 | PackageCleanBeforeInstall: No 21 | PackageInstallArgs: --no-multiarch --with-keep.source 22 | -------------------------------------------------------------------------------- /R/xmldata.R: -------------------------------------------------------------------------------- 1 | find_data_dir <- function(){ 2 | datapath <- c("/share/opencv", "/share/opencv4", "/share/OpenCV") 3 | paths <- c( 4 | system.file('share/opencv4', package = 'opencv'), 5 | system.file('share', package = 'opencv'), 6 | paste0(data_prefix(), datapath) 7 | ) 8 | for(x in paths){ 9 | if(file.exists(x)) 10 | return(x) 11 | } 12 | stop("Failed to find opencv 'share' directory") 13 | } 14 | 15 | find_data_xml <- function(filename){ 16 | normalizePath(file.path(find_data_dir(), filename), mustWork = TRUE) 17 | } 18 | -------------------------------------------------------------------------------- /src/points.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace cv; 4 | using namespace std; 5 | 6 | // [[Rcpp::export]] 7 | XPtrMat cvmat_markers(XPtrMat ptr){ 8 | Mat gray; 9 | Mat image = get_mat(ptr); 10 | cvtColor(image, gray, COLOR_BGR2GRAY); 11 | vector points; 12 | goodFeaturesToTrack(gray, points, 500, 0.01, 10); 13 | 14 | TermCriteria termcrit(TermCriteria::COUNT|TermCriteria::EPS,20,0.03); 15 | cornerSubPix(gray, points, Size(10,10), Size(-1,-1), termcrit); 16 | 17 | for(size_t i = 0; i < points.size(); i++ ) { 18 | circle( image, points[i], 3, Scalar(0,255,0), -1, 8); 19 | } 20 | return ptr; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | 0.5.0 2 | - Windows: use opencv from Rtools when available (R >= 4.5) 3 | 4 | 0.4.0 5 | - Add QR code detector 6 | - Windows: update to libopencv 4.8.1 7 | 8 | 0.3.0 9 | - Windows: update to libopencv 4.8.0 10 | 11 | 0.2.3 12 | - Compile with CXX17 when available to fix compiler warnings 13 | 14 | 0.2.2 15 | - MacOS: update binaries to opencv 4.5.5 16 | 17 | 0.2 18 | - Windows / MacOS: upgrade binary packages to OpenCV 4.4.0 19 | - Add ocv_rectangle 20 | - Add ocv_polygon 21 | - Add ocv_bbox 22 | - Add ocv_chull 23 | - Add ocv_keypoints for keypoint detection using FAST, Harris 24 | - Add ocv_grayscale 25 | - Add ocv_version 26 | 27 | 0.1 28 | - Initial CRAN release 29 | -------------------------------------------------------------------------------- /src/opencv_types.h: -------------------------------------------------------------------------------- 1 | #define R_NO_REMAP 2 | #define STRICT_R_HEADERS 3 | 4 | #include 5 | #include 6 | 7 | #if CV_VERSION_EPOCH >= 3 || (!defined(CV_VERSION_EPOCH) && CV_VERSION_MAJOR >= 3) 8 | #define HAVE_OPENCV_3 9 | #endif 10 | 11 | #if !defined(CV_VERSION_EPOCH) && CV_VERSION_MAJOR >= 4 12 | #define HAVE_OPENCV_4 13 | #endif 14 | 15 | #if (CV_VERSION_MAJOR * 100 + CV_VERSION_MINOR * 10 + CV_VERSION_REVISION >= 452) 16 | #define HAVE_WECHATQR 17 | #endif 18 | 19 | #if (CV_VERSION_MAJOR * 100 + CV_VERSION_MINOR * 10 + CV_VERSION_REVISION >= 344) 20 | #define HAVE_QUIRC 21 | #endif 22 | 23 | void finalize_mat(cv::Mat * frame); 24 | typedef Rcpp::XPtr XPtrMat; 25 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(print,"opencv-image") 4 | export("%>%") 5 | export(ocv_bbox) 6 | export(ocv_bitmap) 7 | export(ocv_blur) 8 | export(ocv_chull) 9 | export(ocv_copyto) 10 | export(ocv_destroy) 11 | export(ocv_display) 12 | export(ocv_edges) 13 | export(ocv_face) 14 | export(ocv_facemask) 15 | export(ocv_grayscale) 16 | export(ocv_hog) 17 | export(ocv_info) 18 | export(ocv_keypoints) 19 | export(ocv_knn) 20 | export(ocv_markers) 21 | export(ocv_mog2) 22 | export(ocv_picture) 23 | export(ocv_polygon) 24 | export(ocv_qr_detect) 25 | export(ocv_read) 26 | export(ocv_rectangle) 27 | export(ocv_resize) 28 | export(ocv_sketch) 29 | export(ocv_stylize) 30 | export(ocv_version) 31 | export(ocv_video) 32 | export(ocv_write) 33 | export(qr_scanner) 34 | importFrom(Rcpp,sourceCpp) 35 | importFrom(magrittr,"%>%") 36 | useDynLib(opencv) 37 | -------------------------------------------------------------------------------- /src/effects.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace cv; 4 | 5 | // [[Rcpp::export]] 6 | XPtrMat cvmat_blur(XPtrMat ptr, size_t ksize){ 7 | Mat out; 8 | cv::blur(get_mat(ptr), out, Size(ksize, ksize)); 9 | return cvmat_xptr(out); 10 | } 11 | 12 | // [[Rcpp::export]] 13 | XPtrMat cvmat_sketch(XPtrMat ptr, bool color){ 14 | Mat out1; 15 | Mat out2; 16 | #ifndef HAVE_OPENCV_3 17 | throw std::runtime_error("pencilSketch requires OpenCV 3 or newer"); 18 | #else 19 | pencilSketch(get_mat(ptr),out1, out2, 10 , 0.1f, 0.03f); 20 | #endif 21 | return cvmat_xptr(color ? out2 : out1); 22 | } 23 | 24 | // [[Rcpp::export]] 25 | XPtrMat cvmat_stylize(XPtrMat ptr){ 26 | Mat out; 27 | #ifndef HAVE_OPENCV_3 28 | throw std::runtime_error("stylization requires OpenCV 3 or newer"); 29 | #else 30 | stylization(get_mat(ptr), out); 31 | #endif 32 | return cvmat_xptr(out); 33 | } 34 | -------------------------------------------------------------------------------- /tools/winlibs.R: -------------------------------------------------------------------------------- 1 | if(!file.exists("../.deps/opencv/include/opencv4/opencv2/opencv.hpp")){ 2 | unlink("../.deps", recursive = TRUE) 3 | url <- if(grepl("aarch", R.version$platform)){ 4 | "https://github.com/r-windows/bundles/releases/download/opencv-4.8.1/opencv-4.8.1-clang-aarch64.tar.xz" 5 | } else if(grepl("clang", Sys.getenv('R_COMPILED_BY'))){ 6 | "https://github.com/r-windows/bundles/releases/download/opencv-4.8.1/opencv-4.8.1-clang-x86_64.tar.xz" 7 | } else if(getRversion() >= "4.3") { 8 | "https://github.com/r-windows/bundles/releases/download/opencv-4.8.1/opencv-4.8.1-ucrt-x86_64.tar.xz" 9 | } else { 10 | "https://github.com/rwinlib/opencv/archive/refs/tags/v4.8.1.tar.gz" 11 | } 12 | download.file(url, basename(url), quiet = TRUE) 13 | dir.create("../.deps", showWarnings = FALSE) 14 | untar(basename(url), exdir = "../.deps", tar = 'internal') 15 | unlink(basename(url)) 16 | setwd("../.deps") 17 | file.rename(list.files(), 'opencv') 18 | } 19 | -------------------------------------------------------------------------------- /R/init.R: -------------------------------------------------------------------------------- 1 | enums <- new.env() 2 | 3 | 4 | .onAttach <- function(libname, pkgname){ 5 | enums$type <- enums_types() 6 | enums$depth <- enums_depth() 7 | } 8 | 9 | enum_label <- function(type, id){ 10 | kv <- enums[[type]] 11 | recoder(id, from = kv$key, to = kv$value) 12 | } 13 | enum_id <- function(type, label){ 14 | kv <- enums[[type]] 15 | recoder(label, from = kv$value, to = kv$key) 16 | } 17 | 18 | .onLoad <- function(libname, pkgname){ 19 | if(is_check()){ 20 | set_num_threads(2) 21 | } 22 | } 23 | 24 | is_macos <- function(){ 25 | grepl("darwin", R.Version()$platform) 26 | } 27 | 28 | is_iterm2 <- function(){ 29 | identical(Sys.getenv('TERM_PROGRAM'), 'iTerm.app') 30 | } 31 | 32 | is_check <- function(){ 33 | grepl('opencv.Rcheck', getwd(), fixed = TRUE) 34 | } 35 | 36 | is_mojave <- function(){ 37 | ver <- utils::tail(strsplit(utils::sessionInfo()$running, ' ')[[1]], 1) 38 | as.numeric_version(ver) >= "10.14" 39 | } 40 | 41 | is_rstudio <- function(){ 42 | Sys.getenv('RSTUDIO') == "1" 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2022 Jeroen Ooms 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: opencv 2 | Type: Package 3 | Title: Bindings to 'OpenCV' Computer Vision Library 4 | Version: 0.5.1 5 | Authors@R: c( 6 | person("Jeroen", "Ooms", role = c("aut", "cre"), email = "jeroenooms@gmail.com", 7 | comment = c(ORCID = "0000-0002-4035-0289")), 8 | person('Jan', 'Wijffels', role = 'aut')) 9 | Description: Exposes some of the available 'OpenCV' algorithms, 10 | such as a QR code scanner, and edge, body or face detection. These can either be 11 | applied to analyze static images, or to filter live video footage from a camera device. 12 | License: MIT + file LICENSE 13 | SystemRequirements: OpenCV 3 or newer: libopencv-dev (Debian, Ubuntu) or opencv-devel (Fedora). 14 | The QR code detector requires at least libopencv 4.5.2. 15 | URL: https://docs.ropensci.org/opencv/ 16 | https://ropensci.r-universe.dev/opencv 17 | BugReports: https://github.com/ropensci/opencv/issues 18 | LinkingTo: Rcpp 19 | Imports: Rcpp, magrittr 20 | Suggests: 21 | grDevices, 22 | qrcode, 23 | testthat (>= 3.0.0) 24 | Encoding: UTF-8 25 | RoxygenNote: 7.2.3 26 | Roxygen: list(markdown = TRUE) 27 | Config/testthat/edition: 3 28 | -------------------------------------------------------------------------------- /src/Makevars.win: -------------------------------------------------------------------------------- 1 | PKG_CONFIG_NAME = opencv4 2 | PKG_CONFIG ?= $(BINPREF)pkg-config 3 | PKG_LIBS := $(shell $(PKG_CONFIG) --libs $(PKG_CONFIG_NAME)) 4 | STATIC_CFLAGS = -DHAVE_XFEATURES2D 5 | 6 | ifneq ($(findstring xfeatures2d,$(PKG_LIBS)),) 7 | $(info using $(PKG_CONFIG_NAME) from Rtools) 8 | PKG_CPPFLAGS := $(shell $(PKG_CONFIG) --cflags $(PKG_CONFIG_NAME)) $(STATIC_CFLAGS) 9 | OPENCVDATA := $(shell $(PKG_CONFIG) --variable=prefix $(PKG_CONFIG_NAME))/share/opencv4 10 | else 11 | RWINLIB = ../.deps/opencv 12 | PKG_CPPFLAGS = -I$(RWINLIB)/include/opencv4 $(STATIC_CFLAGS) 13 | OLDLIBDIR = lib${subst gcc,,${COMPILED_BY}}${R_ARCH} 14 | PKG_LIBS = \ 15 | -L$(RWINLIB)/$(OLDLIBDIR) \ 16 | -L$(RWINLIB)/lib \ 17 | -lopencv_ml481 -lopencv_objdetect481 -lopencv_photo481 -lopencv_stitching481 -lopencv_wechat_qrcode481 -lopencv_dnn481 \ 18 | -lopencv_video481 -lopencv_calib3d481 -lopencv_xfeatures2d481 -lopencv_features2d481 -lopencv_highgui481 -lopencv_flann481 \ 19 | -lopencv_videoio481 -lopencv_imgcodecs481 -lopencv_imgproc481 -lopencv_core481 -llibopenjp2 -lquirc \ 20 | -ljpeg -lwebp -lsharpyuv -lpng -lz -ltiff -lpthread -lgdi32 -lole32 -lopengl32 -lcomdlg32 -lOleAut32 -luuid 21 | OPENCVDATA = $(RWINLIB)/share 22 | endif 23 | 24 | all: copydata 25 | 26 | $(OBJECTS): | $(RWINLIB) 27 | 28 | $(RWINLIB): 29 | "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" "../tools/winlibs.R" 30 | 31 | copydata: | $(RWINLIB) 32 | rm -Rf ../inst/share && mkdir -p ../inst 33 | cp -Rf $(OPENCVDATA) ../inst/share 34 | 35 | cleanup: $(SHLIB) 36 | @rm -Rf $(RWINLIB) 37 | -------------------------------------------------------------------------------- /src/hog.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace cv; 4 | using namespace std; 5 | 6 | // [[Rcpp::export]] 7 | XPtrMat cvmat_hog(XPtrMat ptr){ 8 | HOGDescriptor hog; 9 | hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector()); 10 | vector found, found_filtered; 11 | double t = (double) getTickCount(); 12 | // Run the detector with default parameters. to get a higher hit-rate 13 | // (and more false alarms, respectively), decrease the hitThreshold and 14 | // groupThreshold (set groupThreshold to 0 to turn off the grouping completely). 15 | hog.detectMultiScale(get_mat(ptr), found, 0, Size(8,8), Size(32,32), 1.05, 2); 16 | t = (double) getTickCount() - t; 17 | //cout << "detection time = " << (t*1000./cv::getTickFrequency()) << " ms" << endl; 18 | for(size_t i = 0; i < found.size(); i++ ) 19 | { 20 | Rect r = found[i]; 21 | size_t j; 22 | // Do not add small detections inside a bigger detection. 23 | for ( j = 0; j < found.size(); j++ ){ 24 | if ( j != i && (r & found[j]) == r ) 25 | break; 26 | if ( j == found.size() ) 27 | found_filtered.push_back(r); 28 | } 29 | } 30 | for (size_t i = 0; i < found_filtered.size(); i++) 31 | { 32 | Rect r = found_filtered[i]; 33 | // The HOG detector returns slightly larger rectangles than the real objects, 34 | // so we slightly shrink the rectangles to get a nicer output. 35 | r.x += cvRound(r.width*0.1); 36 | r.width = cvRound(r.width*0.8); 37 | r.y += cvRound(r.height*0.07); 38 | r.height = cvRound(r.height*0.8); 39 | Mat img = get_mat(ptr); 40 | rectangle(img, r.tl(), r.br(), cv::Scalar(0,255,0), 3); 41 | } 42 | return ptr; 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | pull_request: 6 | 7 | name: R-CMD-check.yaml 8 | 9 | permissions: read-all 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macos-13, r: 'release'} 22 | - {os: macos-14, r: 'release'} 23 | - {os: windows-latest, r: '4.1'} 24 | - {os: windows-latest, r: '4.2'} 25 | - {os: windows-latest, r: '4.3'} 26 | - {os: windows-latest, r: '4.4'} 27 | - {os: windows-latest, r: 'devel'} 28 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 29 | - {os: ubuntu-latest, r: 'release'} 30 | - {os: ubuntu-latest, r: 'oldrel-1'} 31 | 32 | env: 33 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 34 | R_KEEP_PKG_SOURCE: yes 35 | 36 | steps: 37 | - uses: actions/checkout@v4 38 | 39 | - uses: r-lib/actions/setup-pandoc@v2 40 | 41 | - uses: r-lib/actions/setup-r@v2 42 | with: 43 | r-version: ${{ matrix.config.r }} 44 | http-user-agent: ${{ matrix.config.http-user-agent }} 45 | use-public-rspm: true 46 | 47 | - uses: r-lib/actions/setup-r-dependencies@v2 48 | with: 49 | extra-packages: any::rcmdcheck 50 | needs: check 51 | 52 | - uses: r-lib/actions/check-r-package@v2 53 | env: 54 | MAKEFLAGS: -j4 55 | -------------------------------------------------------------------------------- /man/opencv-area.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/areas.R 3 | \name{opencv-area} 4 | \alias{opencv-area} 5 | \alias{ocv_rectangle} 6 | \alias{ocv_polygon} 7 | \alias{ocv_bbox} 8 | \alias{ocv_chull} 9 | \title{OpenCV area manipulation} 10 | \usage{ 11 | ocv_rectangle(image, x = 0L, y = 0L, width, height) 12 | 13 | ocv_polygon(image, pts, convex = FALSE, crop = FALSE, color = 255) 14 | 15 | ocv_bbox(image, pts) 16 | 17 | ocv_chull(pts) 18 | } 19 | \arguments{ 20 | \item{image}{an ocv image object} 21 | 22 | \item{x}{horizontal location} 23 | 24 | \item{y}{vertical location} 25 | 26 | \item{width}{width of the area} 27 | 28 | \item{height}{height of the area} 29 | 30 | \item{pts}{a list of points with elements x and y} 31 | 32 | \item{convex}{are the points convex} 33 | 34 | \item{crop}{crop the resulting area to its bounding box} 35 | 36 | \item{color}{color for the non-polygon area} 37 | } 38 | \description{ 39 | Manipulate image regions 40 | } 41 | \examples{ 42 | mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') 43 | 44 | # Rectangular area 45 | ocv_rectangle(mona, x = 400, y = 300, height = 300, width = 350) 46 | ocv_rectangle(mona, x = 0, y = 100, height = 200) 47 | ocv_rectangle(mona, x = 500, y = 0, width = 75) 48 | 49 | # Polygon area 50 | img <- ocv_resize(mona, width = 320, height = 477) 51 | pts <- list(x = c(184, 172, 146, 114, 90, 76, 92, 163, 258), 52 | y = c(72, 68, 70, 90, 110, 398, 412, 385, 210)) 53 | ocv_polygon(img, pts) 54 | ocv_polygon(img, pts, crop = TRUE) 55 | ocv_polygon(img, pts, convex = TRUE, crop = TRUE) 56 | 57 | # Bounding box based on points 58 | ocv_bbox(img, pts) 59 | 60 | # Bounding box of non-zero pixel area 61 | area <- ocv_polygon(img, pts, color = 0, crop = FALSE) 62 | area 63 | area <- ocv_bbox(area) 64 | area 65 | 66 | \dontshow{ 67 | ocv_destroy(mona) 68 | ocv_destroy(img) 69 | ocv_destroy(area) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /man/ocv_keypoints.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/keypoints.R 3 | \name{ocv_keypoints} 4 | \alias{ocv_keypoints} 5 | \title{OpenCV keypoints} 6 | \usage{ 7 | ocv_keypoints( 8 | image, 9 | method = c("FAST", "Harris"), 10 | control = ocv_keypoints_options(method, ...), 11 | ... 12 | ) 13 | } 14 | \arguments{ 15 | \item{image}{an ocv grayscale image object} 16 | 17 | \item{method}{the type of keypoint detection algorithm} 18 | 19 | \item{control}{a list of arguments passed on to the algorithm} 20 | 21 | \item{...}{further arguments passed on to ocv_keypoints_options} 22 | } 23 | \description{ 24 | Find key points in images 25 | } 26 | \section{FAST algorithm arguments}{ 27 | 28 | \itemize{ 29 | \item threshold threshold on difference between intensity of the central pixel and pixels of a circle around this pixel. 30 | \item nonmaxSuppression if true, non-maximum suppression is applied to detected corners (keypoints). 31 | \item type one of the three neighborhoods as defined in the paper: TYPE_9_16, TYPE_7_12, TYPE_5_8 32 | } 33 | } 34 | 35 | \section{Harris algorithm arguments}{ 36 | 37 | \itemize{ 38 | \item numOctaves the number of octaves in the scale-space pyramid 39 | \item corn_thresh the threshold for the Harris cornerness measure 40 | \item DOG_thresh the threshold for the Difference-of-Gaussians scale selection 41 | \item maxCorners the maximum number of corners to consider 42 | \item num_layers the number of intermediate scales per octave 43 | } 44 | } 45 | 46 | \examples{ 47 | mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') 48 | mona <- ocv_resize(mona, width = 320, height = 477) 49 | 50 | # FAST-9 51 | pts <- ocv_keypoints(mona, method = "FAST", type = "TYPE_9_16", threshold = 40) 52 | # Harris 53 | pts <- ocv_keypoints(mona, method = "Harris", maxCorners = 50) 54 | 55 | # Convex Hull of points 56 | pts <- ocv_chull(pts) 57 | 58 | \dontshow{ 59 | ocv_destroy(mona) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /man/qrcode.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/qr.R 3 | \name{ocv_qr_detect} 4 | \alias{ocv_qr_detect} 5 | \alias{qr_scanner} 6 | \title{Detect and Decode a QR code} 7 | \usage{ 8 | ocv_qr_detect(image, draw = FALSE, decoder = c("wechat", "quirc")) 9 | 10 | qr_scanner(draw = FALSE, decoder = c("wechat", "quirc")) 11 | } 12 | \arguments{ 13 | \item{image}{an ocv image object created from e.g. \code{\link[=ocv_read]{ocv_read()}}} 14 | 15 | \item{draw}{if TRUE, the function returns an annotated image showing 16 | the position and value of the QR code.} 17 | 18 | \item{decoder}{which decoder implementation to use, see details.} 19 | } 20 | \value{ 21 | if a QR code is detected, this returns either the text value of the QR, 22 | or if \code{draw} it returns the annotated image, with the value as an attribute. 23 | Returns NULL if no QR was found in the image. 24 | } 25 | \description{ 26 | Detect and decode a QR code from an image or camera. By default it returns 27 | the text value from the QR code if detected, or NULL if no QR was found. If 28 | \code{draw = TRUE} then it returns an annotated image with the position and 29 | value of the QR drawn into the image, and qr text value as an attribute. 30 | The \code{qr_scanner} function opens the camera device (if available on your 31 | computer) and repeats \link{ocv_qr_detect} until it a QR is detected. 32 | } 33 | \details{ 34 | OpenCV has two separate QR decoders. The 'wechat' decoder was added in 35 | libopencv 4.5.2 and generally has better performance and fault-tolerance. 36 | The old 'quirc' decoder is available on some older versions of libopencv as 37 | a plug-in, but many Linux distros did not include it. If you get an error 38 | \emph{Library QUIRC is not linked. No decoding is performed.} this sadly means 39 | your Linux distribution is too old and does not support QR decoding. 40 | } 41 | \examples{ 42 | png("test.png") 43 | plot(qrcode::qr_code("This is a test")) 44 | dev.off() 45 | ocv_qr_detect(ocv_read('test.png')) 46 | unlink("test.png") 47 | } 48 | -------------------------------------------------------------------------------- /R/qr.R: -------------------------------------------------------------------------------- 1 | #' Detect and Decode a QR code 2 | #' 3 | #' Detect and decode a QR code from an image or camera. By default it returns 4 | #' the text value from the QR code if detected, or NULL if no QR was found. If 5 | #' `draw = TRUE` then it returns an annotated image with the position and 6 | #' value of the QR drawn into the image, and qr text value as an attribute. 7 | #' The `qr_scanner` function opens the camera device (if available on your 8 | #' computer) and repeats [ocv_qr_detect] until it a QR is detected. 9 | #' 10 | #' OpenCV has two separate QR decoders. The 'wechat' decoder was added in 11 | #' libopencv 4.5.2 and generally has better performance and fault-tolerance. 12 | #' The old 'quirc' decoder is available on some older versions of libopencv as 13 | #' a plug-in, but many Linux distros did not include it. If you get an error 14 | #' *Library QUIRC is not linked. No decoding is performed.* this sadly means 15 | #' your Linux distribution is too old and does not support QR decoding. 16 | #' 17 | #' @export 18 | #' @rdname qrcode 19 | #' @inheritParams ocv_write 20 | #' @param draw if TRUE, the function returns an annotated image showing 21 | #' the position and value of the QR code. 22 | #' @param decoder which decoder implementation to use, see details. 23 | #' @returns if a QR code is detected, this returns either the text value of the QR, 24 | #' or if `draw` it returns the annotated image, with the value as an attribute. 25 | #' Returns NULL if no QR was found in the image. 26 | #' @examples 27 | #' png("test.png") 28 | #' plot(qrcode::qr_code("This is a test")) 29 | #' dev.off() 30 | #' ocv_qr_detect(ocv_read('test.png')) 31 | #' unlink("test.png") 32 | ocv_qr_detect <- function(image, draw = FALSE, decoder = c("wechat", "quirc")){ 33 | draw <- as.logical(draw) 34 | use_wechat <- match.arg(decoder) == 'wechat' 35 | cvmat_qr_detect(image, draw, use_wechat) 36 | } 37 | 38 | #' @export 39 | #' @rdname qrcode 40 | qr_scanner <- function(draw = FALSE, decoder = c("wechat", "quirc")){ 41 | ocv_video(function(image) { 42 | ocv_qr_detect(image = image, draw = draw, decoder = decoder) 43 | }, stop_on_result = TRUE) 44 | } 45 | -------------------------------------------------------------------------------- /src/qrdetect.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | using namespace cv; 3 | 4 | #ifdef HAVE_WECHATQR 5 | #include 6 | static std::string qr_scan_wechat(XPtrMat ptr, Mat &points){ 7 | static wechat_qrcode::WeChatQRCode qrDet = wechat_qrcode::WeChatQRCode(); 8 | std::vector pointsvec; 9 | std::vector data = qrDet.detectAndDecode(get_mat(ptr), pointsvec); 10 | if(data.size() > 0){ 11 | points = pointsvec.at(0); 12 | return data.at(0); 13 | } 14 | return std::string(); 15 | } 16 | #endif 17 | 18 | static std::string qr_scan_opencv(XPtrMat ptr, Mat &points){ 19 | #ifdef HAVE_QUIRC 20 | static QRCodeDetector qrDet = QRCodeDetector(); 21 | return qrDet.detectAndDecode(get_mat(ptr), points); 22 | #else 23 | throw std::runtime_error("QR scanner requires OpenCV 3.4.4 or newer"); 24 | #endif 25 | } 26 | 27 | // [[Rcpp::export]] 28 | SEXP cvmat_qr_detect(XPtrMat ptr, bool return_image = false, bool use_wechat = true){ 29 | Mat points; 30 | #ifdef HAVE_WECHATQR 31 | std::string data = use_wechat ? qr_scan_wechat(ptr, points) : qr_scan_opencv(ptr, points); 32 | #else 33 | std::string data = qr_scan_opencv(ptr, points); 34 | #endif 35 | if(!data.length()) 36 | return R_NilValue; 37 | if(!use_wechat) 38 | points = points.reshape(1, 4); 39 | int len = points.size().height; 40 | Rcpp::IntegerMatrix corners(len, 2); 41 | for (int i = 0; i < len; i++) { 42 | Point pt = cv::Point(points.row(i)); 43 | corners[i] = pt.x; 44 | corners[i+len] = pt.y; 45 | } 46 | if(!return_image){ 47 | Rcpp::CharacterVector out(data); 48 | out.attr("points") = corners; 49 | return out; 50 | } 51 | cv::Mat img = get_mat(ptr); 52 | for (int i = 0; i < len; i++) { 53 | Point pt1 = cv::Point(points.row(i)); 54 | Point pt2 = cv::Point(points.row((i + 1) % 4)); 55 | line(img, pt1, pt2, Scalar(255, 0, 0), 3); 56 | } 57 | cv::putText(img, data, 58 | cv::Point(10, img.rows / 2), //left-middle position 59 | cv::FONT_HERSHEY_DUPLEX, 60 | 1.0, 61 | CV_RGB(118, 185, 0), //font color 62 | 2); 63 | ptr.attr("value") = Rcpp::CharacterVector::create(data); 64 | ptr.attr("points") = corners; 65 | return ptr; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /R/areas.R: -------------------------------------------------------------------------------- 1 | #' OpenCV area manipulation 2 | #' 3 | #' Manipulate image regions 4 | #' @name opencv-area 5 | #' @rdname opencv-area 6 | #' @param image an ocv image object 7 | #' @param x horizontal location 8 | #' @param y vertical location 9 | #' @param width width of the area 10 | #' @param height height of the area 11 | #' @export 12 | #' @examples 13 | #' mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') 14 | #' 15 | #' # Rectangular area 16 | #' ocv_rectangle(mona, x = 400, y = 300, height = 300, width = 350) 17 | #' ocv_rectangle(mona, x = 0, y = 100, height = 200) 18 | #' ocv_rectangle(mona, x = 500, y = 0, width = 75) 19 | #' 20 | #' # Polygon area 21 | #' img <- ocv_resize(mona, width = 320, height = 477) 22 | #' pts <- list(x = c(184, 172, 146, 114, 90, 76, 92, 163, 258), 23 | #' y = c(72, 68, 70, 90, 110, 398, 412, 385, 210)) 24 | #' ocv_polygon(img, pts) 25 | #' ocv_polygon(img, pts, crop = TRUE) 26 | #' ocv_polygon(img, pts, convex = TRUE, crop = TRUE) 27 | #' 28 | #' # Bounding box based on points 29 | #' ocv_bbox(img, pts) 30 | #' 31 | #' # Bounding box of non-zero pixel area 32 | #' area <- ocv_polygon(img, pts, color = 0, crop = FALSE) 33 | #' area 34 | #' area <- ocv_bbox(area) 35 | #' area 36 | #' 37 | #' \dontshow{ 38 | #' ocv_destroy(mona) 39 | #' ocv_destroy(img) 40 | #' ocv_destroy(area) 41 | #' } 42 | ocv_rectangle <- function(image, x = 0L, y = 0L, width, height){ 43 | size <- ocv_info(image) 44 | if(missing(width)){ 45 | width <- size$width 46 | } 47 | if(missing(height)){ 48 | height <- size$height 49 | } 50 | cvmat_rect(image, x, y, width, height) 51 | } 52 | 53 | #' @export 54 | #' @rdname opencv-area 55 | #' @param pts a list of points with elements x and y 56 | #' @param convex are the points convex 57 | #' @param crop crop the resulting area to its bounding box 58 | #' @param color color for the non-polygon area 59 | ocv_polygon <- function(image, pts, convex = FALSE, crop = FALSE, color = 255){ 60 | stopifnot(is.list(pts) && all(c("x", "y") %in% names(pts))) 61 | cvmat_polygon(image, pts, convex, crop, color) 62 | } 63 | 64 | #' @export 65 | #' @rdname opencv-area 66 | #' @param pts a list of points with elements x and y 67 | ocv_bbox <- function(image, pts){ 68 | if(missing(pts)){ 69 | cvmat_bbox(image) 70 | }else{ 71 | stopifnot(is.list(pts) && all(c("x", "y") %in% names(pts))) 72 | cvpoints_bbox(image, pts) 73 | } 74 | } 75 | 76 | #' @export 77 | #' @rdname opencv-area 78 | #' @param pts a list of points with elements x and y 79 | ocv_chull <- function(pts){ 80 | stopifnot(is.list(pts) && all(c("x", "y") %in% names(pts))) 81 | cvpoints_chull(pts) 82 | } 83 | -------------------------------------------------------------------------------- /man/opencv.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/face.R, R/opencv.R 3 | \name{ocv_face} 4 | \alias{ocv_face} 5 | \alias{ocv_facemask} 6 | \alias{ocv_read} 7 | \alias{ocv_write} 8 | \alias{ocv_destroy} 9 | \alias{ocv_bitmap} 10 | \alias{ocv_edges} 11 | \alias{ocv_picture} 12 | \alias{ocv_resize} 13 | \alias{ocv_mog2} 14 | \alias{ocv_knn} 15 | \alias{ocv_hog} 16 | \alias{ocv_blur} 17 | \alias{ocv_sketch} 18 | \alias{ocv_stylize} 19 | \alias{ocv_markers} 20 | \alias{ocv_info} 21 | \alias{ocv_copyto} 22 | \alias{ocv_display} 23 | \alias{ocv_video} 24 | \alias{ocv_grayscale} 25 | \alias{ocv_version} 26 | \title{OpenCV Computer Vision} 27 | \usage{ 28 | ocv_face(image) 29 | 30 | ocv_facemask(image) 31 | 32 | ocv_read(path) 33 | 34 | ocv_write(image, path) 35 | 36 | ocv_destroy(image) 37 | 38 | ocv_bitmap(image) 39 | 40 | ocv_edges(image) 41 | 42 | ocv_picture() 43 | 44 | ocv_resize(image, width = 0, height = 0) 45 | 46 | ocv_mog2(image) 47 | 48 | ocv_knn(image) 49 | 50 | ocv_hog(image) 51 | 52 | ocv_blur(image, ksize = 5) 53 | 54 | ocv_sketch(image, color = TRUE) 55 | 56 | ocv_stylize(image) 57 | 58 | ocv_markers(image) 59 | 60 | ocv_info(image) 61 | 62 | ocv_copyto(image, target, mask) 63 | 64 | ocv_display(image) 65 | 66 | ocv_video(filter, stop_on_result = FALSE) 67 | 68 | ocv_grayscale(image) 69 | 70 | ocv_version() 71 | } 72 | \arguments{ 73 | \item{image}{an ocv image object created from e.g. \code{\link[=ocv_read]{ocv_read()}}} 74 | 75 | \item{path}{image file such as png or jpeg} 76 | 77 | \item{width}{output width in pixels} 78 | 79 | \item{height}{output height in pixels} 80 | 81 | \item{ksize}{size of blurring matrix} 82 | 83 | \item{color}{true or false} 84 | 85 | \item{target}{the output image} 86 | 87 | \item{mask}{only copy pixels from the mask} 88 | 89 | \item{filter}{an R function that takes and returns an opecv image} 90 | 91 | \item{stop_on_result}{stop if an object is detected} 92 | } 93 | \description{ 94 | Tools to experiment with computer vision algorithms. Use \link{ocv_read} and 95 | \link{ocv_write} to load/save images on disk, or use \link{ocv_picture} / \link{ocv_video} 96 | to use your webcam. In RSudio IDE the image objects will automatically be 97 | displayed in the viewer pane. 98 | } 99 | \examples{ 100 | # Silly example 101 | mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') 102 | 103 | # Edge detection 104 | ocv_edges(mona) 105 | ocv_markers(mona) 106 | 107 | # Find face 108 | faces <- ocv_face(mona) 109 | 110 | # To show locations of faces 111 | facemask <- ocv_facemask(mona) 112 | attr(facemask, 'faces') 113 | 114 | # This is not strictly needed 115 | ocv_destroy(mona) 116 | } 117 | -------------------------------------------------------------------------------- /R/keypoints.R: -------------------------------------------------------------------------------- 1 | #' OpenCV keypoints 2 | #' 3 | #' Find key points in images 4 | #' @param image an ocv grayscale image object 5 | #' @param method the type of keypoint detection algorithm 6 | #' @param control a list of arguments passed on to the algorithm 7 | #' @param ... further arguments passed on to ocv_keypoints_options 8 | #' @section FAST algorithm arguments: 9 | #' \itemize{ 10 | #' \item threshold threshold on difference between intensity of the central pixel and pixels of a circle around this pixel. 11 | #' \item nonmaxSuppression if true, non-maximum suppression is applied to detected corners (keypoints). 12 | #' \item type one of the three neighborhoods as defined in the paper: TYPE_9_16, TYPE_7_12, TYPE_5_8 13 | #' } 14 | #' @section Harris algorithm arguments: 15 | #' \itemize{ 16 | #' \item numOctaves the number of octaves in the scale-space pyramid 17 | #' \item corn_thresh the threshold for the Harris cornerness measure 18 | #' \item DOG_thresh the threshold for the Difference-of-Gaussians scale selection 19 | #' \item maxCorners the maximum number of corners to consider 20 | #' \item num_layers the number of intermediate scales per octave 21 | #' } 22 | #' @export 23 | #' @examples 24 | #' mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') 25 | #' mona <- ocv_resize(mona, width = 320, height = 477) 26 | #' 27 | #' # FAST-9 28 | #' pts <- ocv_keypoints(mona, method = "FAST", type = "TYPE_9_16", threshold = 40) 29 | #' # Harris 30 | #' pts <- ocv_keypoints(mona, method = "Harris", maxCorners = 50) 31 | #' 32 | #' # Convex Hull of points 33 | #' pts <- ocv_chull(pts) 34 | #' 35 | #' \dontshow{ 36 | #' ocv_destroy(mona) 37 | #' } 38 | ocv_keypoints <- function(image, method = c("FAST", "Harris"), control = ocv_keypoints_options(method, ...), ...){ 39 | method <- match.arg(method) 40 | params <- control 41 | if(method == "FAST"){ 42 | cvkeypoints_fast(image, params$threshold, params$nonmaxSuppression, params$type) 43 | }else if(method == "Harris"){ 44 | cvkeypoints_harris(image, params$numOctaves, params$corn_thresh, params$DOG_thresh, params$maxCorners, params$num_layers) 45 | } 46 | } 47 | 48 | ocv_keypoints_options <- function(method = c("FAST", "Harris"), ...){ 49 | method <- match.arg(method) 50 | ldots <- list(...) 51 | if(method == "FAST"){ 52 | params <- list(threshold = 0, nonmaxSuppression = TRUE, type = c("TYPE_9_16", "TYPE_7_12", "TYPE_5_8")) 53 | }else if(method == "Harris"){ 54 | params <- list(numOctaves = 6, corn_thresh = 0.01, DOG_thresh = 0.01, maxCorners = 5000, num_layers = 4) 55 | } 56 | for(i in intersect(names(params), names(ldots))){ 57 | params[[i]] <- ldots[[i]] 58 | } 59 | if(is.character(params$type)){ 60 | params$type <- switch(params$type, "TYPE_5_8" = 0L, "TYPE_7_12" = 1L, "TYPE_9_16" = 2L) 61 | } 62 | params 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/features.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "util.hpp" 3 | #include 4 | #include 5 | #ifdef HAVE_XFEATURES2D 6 | #include 7 | #endif 8 | 9 | 10 | Rcpp::List keypoints_coords(const std::vector& pts){ 11 | std::vector x; 12 | std::vector y; 13 | for (size_t i = 0; i < pts.size(); ++i){ 14 | x.push_back(pts[i].pt.x); 15 | y.push_back(pts[i].pt.y); 16 | } 17 | Rcpp::List out = Rcpp::List::create(Rcpp::Named("x") = x, 18 | Rcpp::Named("y") = y); 19 | return out; 20 | } 21 | 22 | 23 | // [[Rcpp::export]] 24 | Rcpp::List cvkeypoints_fast(XPtrMat ptr, int threshold = 0, bool nonmaxSuppression = true, int type = 2){ 25 | cv::Mat img; 26 | cv::cvtColor(get_mat(ptr), img, cv::COLOR_BGR2GRAY); 27 | std::vector keypoints; 28 | #ifndef HAVE_XFEATURES2D 29 | Rcpp::Rcout << "Keypoint detection disabled as module xfeatures2d from opencv_contrib is not present." << std::endl; 30 | return keypoints_coords(keypoints); 31 | #else 32 | // versions < 4 had CV_VERSION_EPOCH instead of CV_VERSION_MAJOR and cv::FastFeatureDetector::DetectorType did not exist (was just an integer) 33 | #ifndef HAVE_OPENCV_4 34 | int neighbourhood; 35 | #else 36 | cv::FastFeatureDetector::DetectorType neighbourhood; 37 | #endif 38 | switch(type){ 39 | case cv::FastFeatureDetector::TYPE_9_16: 40 | neighbourhood = cv::FastFeatureDetector::TYPE_9_16; 41 | break; 42 | case cv::FastFeatureDetector::TYPE_7_12: 43 | neighbourhood = cv::FastFeatureDetector::TYPE_7_12; 44 | break; 45 | case cv::FastFeatureDetector::TYPE_5_8: 46 | neighbourhood = cv::FastFeatureDetector::TYPE_5_8; 47 | break; 48 | default: 49 | neighbourhood = cv::FastFeatureDetector::TYPE_9_16; 50 | break; 51 | } 52 | cv::xfeatures2d::FASTForPointSet(img, keypoints, threshold, nonmaxSuppression, neighbourhood); 53 | return keypoints_coords(keypoints); 54 | #endif 55 | } 56 | 57 | 58 | // [[Rcpp::export]] 59 | Rcpp::List cvkeypoints_harris(XPtrMat ptr, 60 | int numOctaves = 6, float corn_thresh = 0.01, float DOG_thresh = 0.01, int maxCorners = 5000, int num_layers = 4){ 61 | cv::Mat img; 62 | cv::cvtColor(get_mat(ptr), img, cv::COLOR_BGR2GRAY); 63 | std::vector keypoints; 64 | #ifndef HAVE_XFEATURES2D 65 | Rcpp::Rcout << "Keypoint detection disabled as module xfeatures2d from opencv_contrib is not present." << std::endl; 66 | return keypoints_coords(keypoints); 67 | #else 68 | auto featureDetector = cv::xfeatures2d::HarrisLaplaceFeatureDetector::create(numOctaves, corn_thresh, DOG_thresh, maxCorners, num_layers); 69 | featureDetector->detect(img, keypoints); 70 | return keypoints_coords(keypoints); 71 | #endif 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/areas.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | #include 3 | #include 4 | 5 | std::vector as_points(Rcpp::List pts){ 6 | std::vector points; 7 | std::vector x = Rcpp::as>(pts["x"]); 8 | std::vector y = Rcpp::as>(pts["y"]); 9 | for (size_t i = 0; i < x.size(); ++i){ 10 | cv::Point2i pt(x[i], y[i]); 11 | points.push_back(pt); 12 | } 13 | return points; 14 | } 15 | 16 | Rcpp::List points_coords(const std::vector& pts){ 17 | std::vector x; 18 | std::vector y; 19 | for (size_t i = 0; i < pts.size(); ++i){ 20 | x.push_back(pts[i].x); 21 | y.push_back(pts[i].y); 22 | } 23 | Rcpp::List out = Rcpp::List::create(Rcpp::Named("x") = x, 24 | Rcpp::Named("y") = y); 25 | return out; 26 | } 27 | 28 | // [[Rcpp::export]] 29 | XPtrMat cvmat_rect(XPtrMat ptr, int x = 0, int y = 0, int width = 0, int height = 0){ 30 | cv::Mat img = get_mat(ptr); 31 | cv::Rect roi = cv::Rect(x, y, width, height); 32 | cv::Mat output = img(roi); 33 | return cvmat_xptr(output); 34 | } 35 | 36 | // [[Rcpp::export]] 37 | XPtrMat cvmat_bbox(XPtrMat ptr){ 38 | #ifndef HAVE_OPENCV_3 39 | Rcpp::Rcout << "ocv_bbox works only if you provide points in your version of opencv, returning original image" << std::endl; 40 | return ptr; 41 | #else 42 | cv::Mat img = get_mat(ptr); 43 | cv::Mat output; 44 | cv::Rect roi; 45 | if(img.channels() > 1){ 46 | cv::Mat img_gray; 47 | cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY); 48 | roi = cv::boundingRect(img_gray); 49 | }else{ 50 | roi = cv::boundingRect(img); 51 | } 52 | output = img(roi); 53 | return cvmat_xptr(output); 54 | #endif 55 | } 56 | 57 | // [[Rcpp::export]] 58 | XPtrMat cvpoints_bbox(XPtrMat ptr, Rcpp::List pts){ 59 | cv::Mat img = get_mat(ptr); 60 | auto points = as_points(pts); 61 | cv::Rect roi = cv::boundingRect(points); 62 | cv::Mat output = img(roi); 63 | return cvmat_xptr(output); 64 | } 65 | 66 | // [[Rcpp::export]] 67 | Rcpp::List cvpoints_chull(Rcpp::List pts){ 68 | std::vector points = as_points(pts); 69 | if(points.size() == 0){ 70 | return points_coords(points); 71 | } 72 | std::vector points_chull; 73 | cv::convexHull(points, points_chull); 74 | return points_coords(points_chull); 75 | } 76 | 77 | 78 | // [[Rcpp::export]] 79 | XPtrMat cvmat_polygon(XPtrMat ptr, Rcpp::List pts, bool convex = false, bool crop = false, int color = 255){ 80 | auto points = as_points(pts); 81 | cv::Mat img = get_mat(ptr); 82 | cv::Mat mask = cv::Mat::zeros(img.rows, img.cols, CV_8U); 83 | if(convex){ 84 | cv::fillConvexPoly(mask, points, cv::Scalar(255, 255, 255)); 85 | }else{ 86 | std::vector> polygons; 87 | polygons.push_back(points); 88 | cv::fillPoly(mask, polygons, cv::Scalar(255, 255, 255)); 89 | } 90 | cv::Mat area(img.rows, img.cols, img.type()); 91 | area.setTo(cv::Scalar(color, color, color)); 92 | img.copyTo(area, mask); 93 | if(crop){ 94 | cv::Rect roi = cv::boundingRect(points); 95 | return cvmat_xptr(area(roi)); 96 | } 97 | return cvmat_xptr(area); 98 | } 99 | 100 | -------------------------------------------------------------------------------- /src/face.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace cv; 4 | 5 | // [[Rcpp::export]] 6 | XPtrMat cvmat_face(XPtrMat ptr, const char * facedata, const char * eyedata){ 7 | /* load training data */ 8 | CascadeClassifier face, eyes; 9 | if(!face.load( facedata )) 10 | throw std::runtime_error(std::string("Failed to load: ") + facedata); 11 | if(!eyes.load( eyedata )) 12 | throw std::runtime_error(std::string("Failed to load: ") + eyedata); 13 | 14 | //modify in place 15 | detectAndDraw(get_mat(ptr), face, eyes, 1, 0); 16 | return ptr; 17 | } 18 | 19 | // [[Rcpp::export]] 20 | XPtrMat cvmat_facemask(XPtrMat ptr, const char * facedata){ 21 | /* load training data */ 22 | CascadeClassifier face; 23 | if(!face.load( facedata )) 24 | throw std::runtime_error(std::string("Failed to load: ") + facedata); 25 | 26 | Mat gray; 27 | Mat input = get_mat(ptr); 28 | cvtColor( input, gray, COLOR_BGR2GRAY ); 29 | equalizeHist(gray, gray); 30 | std::vector faces; 31 | face.detectMultiScale( gray, faces, 1.1, 2, 0 32 | //|CASCADE_FIND_BIGGEST_OBJECT 33 | //|CASCADE_DO_ROUGH_SEARCH 34 | |CASCADE_SCALE_IMAGE, 35 | Size(30, 30) ); 36 | 37 | Mat mask(gray.size(), gray.type(), Scalar::all(0)); 38 | Rcpp::IntegerVector rvec(faces.size()); 39 | Rcpp::IntegerVector xvec(faces.size()); 40 | Rcpp::IntegerVector yvec(faces.size()); 41 | for ( size_t i = 0; i < faces.size(); i++ ) { 42 | Point center; 43 | Rect r = faces.at(i); 44 | center.x = cvRound((r.x + r.width*0.5)); 45 | center.y = cvRound((r.y + r.height*0.5)); 46 | int radius = cvRound((r.width + r.height)*0.25); 47 | circle( mask, center, radius, Scalar::all(255), -1); 48 | rvec.at(i) = radius; 49 | xvec.at(i) = center.x; 50 | yvec.at(i) = center.y; 51 | } 52 | XPtrMat out = cvmat_xptr(mask); 53 | out.attr("faces") = Rcpp::DataFrame::create( 54 | Rcpp::_["radius"] = rvec, 55 | Rcpp::_["x"] = xvec, 56 | Rcpp::_["y"] = yvec 57 | ); 58 | return out; 59 | } 60 | 61 | // [[Rcpp::export]] 62 | XPtrMat cvmat_mog2(XPtrMat ptr) { 63 | #ifndef HAVE_OPENCV_3 64 | throw std::runtime_error("createBackgroundSubtractorMOG2 requires OpenCV 3 or newer"); 65 | #else 66 | static Ptr model = createBackgroundSubtractorMOG2(); 67 | model->setVarThreshold(10); 68 | cv::Mat frame = get_mat(ptr); 69 | cv::Mat mask, out_frame; 70 | model->apply(frame, mask); 71 | //refineSegments(frame, mask, out_frame); 72 | return cvmat_xptr(mask); 73 | #endif 74 | } 75 | 76 | // [[Rcpp::export]] 77 | XPtrMat cvmat_knn(XPtrMat ptr) { 78 | #ifndef HAVE_OPENCV_3 79 | throw std::runtime_error("createBackgroundSubtractorKNN requires OpenCV 3 or newer"); 80 | #else 81 | static Ptr model = createBackgroundSubtractorKNN(); 82 | cv::Mat frame = get_mat(ptr); 83 | cv::Mat mask, out_frame; 84 | model->apply(frame, mask); 85 | return cvmat_xptr(mask); 86 | #endif 87 | } 88 | 89 | // [[Rcpp::export]] 90 | XPtrMat cvmat_edges(XPtrMat ptr) { 91 | cv::Mat edges; 92 | cv::Mat frame = get_mat(ptr); 93 | cvtColor(frame, edges, COLOR_BGR2GRAY); 94 | GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5); 95 | Canny(edges, edges, 0, 30, 3); 96 | return cvmat_xptr(edges); 97 | } 98 | -------------------------------------------------------------------------------- /src/enums.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | // [[Rcpp::export]] 6 | Rcpp::List enums_types(int maximum = 4){ 7 | std::vector key; 8 | std::vector value; 9 | 10 | #ifdef CV_8U 11 | key.push_back(CV_8U); 12 | value.push_back("CV_8U"); 13 | for(int i = 1; i <= maximum; i++){ 14 | key.push_back(CV_MAKETYPE(CV_8U, i)); 15 | value.push_back("CV_8U" + std::to_string(i)); 16 | } 17 | #endif 18 | #ifdef CV_8S 19 | key.push_back(CV_8S); 20 | value.push_back("CV_8S"); 21 | for(int i = 1; i <= maximum; i++){ 22 | key.push_back(CV_MAKETYPE(CV_8S, i)); 23 | value.push_back("CV_8S" + std::to_string(i)); 24 | } 25 | #endif 26 | #ifdef CV_16U 27 | key.push_back(CV_16U); 28 | value.push_back("CV_16U"); 29 | for(int i = 1; i <= maximum; i++){ 30 | key.push_back(CV_MAKETYPE(CV_16U, i)); 31 | value.push_back("CV_16U" + std::to_string(i)); 32 | } 33 | #endif 34 | #ifdef CV_16S 35 | key.push_back(CV_16S); 36 | value.push_back("CV_16S"); 37 | for(int i = 1; i <= maximum; i++){ 38 | key.push_back(CV_MAKETYPE(CV_16S, i)); 39 | value.push_back("CV_16S" + std::to_string(i)); 40 | } 41 | #endif 42 | #ifdef CV_16F 43 | key.push_back(CV_16F); 44 | value.push_back("CV_16F"); 45 | for(int i = 1; i <= maximum; i++){ 46 | key.push_back(CV_MAKETYPE(CV_16F, i)); 47 | value.push_back("CV_16F" + std::to_string(i)); 48 | } 49 | #endif 50 | #ifdef CV_32S 51 | key.push_back(CV_32S); 52 | value.push_back("CV_32S"); 53 | for(int i = 1; i <= maximum; i++){ 54 | key.push_back(CV_MAKETYPE(CV_32S, i)); 55 | value.push_back("CV_32S" + std::to_string(i)); 56 | } 57 | #endif 58 | #ifdef CV_32F 59 | key.push_back(CV_32F); 60 | value.push_back("CV_32F"); 61 | for(int i = 1; i <= maximum; i++){ 62 | key.push_back(CV_MAKETYPE(CV_32F, i)); 63 | value.push_back("CV_32F" + std::to_string(i)); 64 | } 65 | #endif 66 | #ifdef CV_64F 67 | key.push_back(CV_64F); 68 | value.push_back("CV_64F"); 69 | for(int i = 1; i <= maximum; i++){ 70 | key.push_back(CV_MAKETYPE(CV_64F, i)); 71 | value.push_back("CV_64F" + std::to_string(i)); 72 | } 73 | #endif 74 | Rcpp::List out = Rcpp::List::create(Rcpp::Named("key") = key, 75 | Rcpp::Named("value") = value); 76 | return out; 77 | } 78 | 79 | 80 | // [[Rcpp::export]] 81 | Rcpp::List enums_depth(){ 82 | std::vector key; 83 | std::vector value; 84 | 85 | #ifdef CV_8U 86 | key.push_back(CV_8U); 87 | value.push_back("CV_8U"); 88 | #endif 89 | #ifdef CV_8S 90 | key.push_back(CV_8S); 91 | value.push_back("CV_8S"); 92 | #endif 93 | #ifdef CV_16U 94 | key.push_back(CV_16U); 95 | value.push_back("CV_16U"); 96 | #endif 97 | #ifdef CV_16S 98 | key.push_back(CV_16S); 99 | value.push_back("CV_16S"); 100 | #endif 101 | #ifdef CV_16F 102 | key.push_back(CV_16F); 103 | value.push_back("CV_16F"); 104 | #endif 105 | #ifdef CV_32S 106 | key.push_back(CV_32S); 107 | value.push_back("CV_32S"); 108 | #endif 109 | #ifdef CV_32F 110 | key.push_back(CV_32F); 111 | value.push_back("CV_32F"); 112 | #endif 113 | #ifdef CV_64F 114 | key.push_back(CV_64F); 115 | value.push_back("CV_64F"); 116 | #endif 117 | Rcpp::List out = Rcpp::List::create(Rcpp::Named("key") = key, 118 | Rcpp::Named("value") = value); 119 | return out; 120 | } 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | using namespace cv; 4 | using namespace std; 5 | 6 | void detectAndDraw( Mat img, CascadeClassifier& cascade, 7 | CascadeClassifier& nestedCascade, 8 | double scale, bool tryflip ) 9 | { 10 | double t = 0; 11 | std::vector faces, faces2; 12 | const static Scalar colors[] = 13 | { 14 | Scalar(255,0,0), 15 | Scalar(255,128,0), 16 | Scalar(255,255,0), 17 | Scalar(0,255,0), 18 | Scalar(0,128,255), 19 | Scalar(0,255,255), 20 | Scalar(0,0,255), 21 | Scalar(255,0,255) 22 | }; 23 | Mat gray, smallImg; 24 | cvtColor( img, gray, COLOR_BGR2GRAY ); 25 | double fx = 1 / scale; 26 | resize( gray, smallImg, Size(), fx, fx); 27 | equalizeHist( smallImg, smallImg ); 28 | t = (double)getTickCount(); 29 | cascade.detectMultiScale( smallImg, faces, 30 | 1.1, 2, 0 31 | //|CASCADE_FIND_BIGGEST_OBJECT 32 | //|CASCADE_DO_ROUGH_SEARCH 33 | |CASCADE_SCALE_IMAGE, 34 | Size(30, 30) ); 35 | if( tryflip ) 36 | { 37 | flip(smallImg, smallImg, 1); 38 | cascade.detectMultiScale( smallImg, faces2, 39 | 1.1, 2, 0 40 | //|CASCADE_FIND_BIGGEST_OBJECT 41 | //|CASCADE_DO_ROUGH_SEARCH 42 | |CASCADE_SCALE_IMAGE, 43 | Size(30, 30) ); 44 | for( std::vector::const_iterator r = faces2.begin(); r != faces2.end(); ++r ) 45 | { 46 | faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height)); 47 | } 48 | } 49 | t = (double)getTickCount() - t; 50 | //printf( "detection time = %g ms\n", t*1000/getTickFrequency()); 51 | for ( size_t i = 0; i < faces.size(); i++ ) 52 | { 53 | Rect r = faces[i]; 54 | Mat smallImgROI; 55 | std::vector nestedObjects; 56 | Point center; 57 | Scalar color = colors[i%8]; 58 | int radius; 59 | double aspect_ratio = (double)r.width/r.height; 60 | if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ) 61 | { 62 | center.x = cvRound((r.x + r.width*0.5)*scale); 63 | center.y = cvRound((r.y + r.height*0.5)*scale); 64 | radius = cvRound((r.width + r.height)*0.25*scale); 65 | circle( img, center, radius, color, 3, 8, 0 ); 66 | } 67 | else 68 | rectangle( img, cv::Point(cvRound(r.x*scale), cvRound(r.y*scale)), 69 | cv::Point(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)), 70 | color, 3, 8, 0); 71 | if( nestedCascade.empty() ) 72 | continue; 73 | smallImgROI = smallImg( r ); 74 | nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 75 | 1.1, 2, 0 76 | //|CASCADE_FIND_BIGGEST_OBJECT 77 | //|CASCADE_DO_ROUGH_SEARCH 78 | //|CASCADE_DO_CANNY_PRUNING 79 | |CASCADE_SCALE_IMAGE, 80 | Size(30, 30) ); 81 | for ( size_t j = 0; j < nestedObjects.size(); j++ ) 82 | { 83 | Rect nr = nestedObjects[j]; 84 | center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale); 85 | center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale); 86 | radius = cvRound((nr.width + nr.height)*0.25*scale); 87 | circle( img, center, radius, color, 3, 8, 0 ); 88 | } 89 | } 90 | //imshow( "result", img ); 91 | } 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bindings to 'OpenCV' Computer Vision Library 2 | 3 | > Experimenting with computer vision and machine learning in R. This 4 | package exposes some of the available 'OpenCV' algorithms, 5 | such as edge, body or face detection. These can either be applied to analyze 6 | static images, or to filter live video footage from a camera device. 7 | 8 | [![CRAN_Status_Badge](http://www.r-pkg.org/badges/version/opencv)](http://cran.r-project.org/package=opencv) 9 | [![CRAN RStudio mirror downloads](http://cranlogs.r-pkg.org/badges/opencv)](http://cran.r-project.org/web/packages/opencv/index.html) 10 | 11 | 12 | ## Installation 13 | 14 | On Windows and MacOS, the package can be installed directoy from CRAN: 15 | 16 | ```r 17 | install.packages("opencv") 18 | ``` 19 | 20 | ### Install from source 21 | 22 | To install from source on MacOS, you need to install the opencv library from homebrew: 23 | 24 | ```sh 25 | brew install opencv 26 | ``` 27 | 28 | On Ubuntu or Fedora you need [`libopencv-dev`](https://packages.debian.org/testing/libopencv-dev) or [`opencv-devel`](https://src.fedoraproject.org/rpms/opencv): 29 | 30 | ```sh 31 | sudo apt-get install libopencv-dev 32 | ``` 33 | 34 | And then install the R bindings: 35 | 36 | ```r 37 | install.packages("opencv", type = "source") 38 | ``` 39 | 40 | ## Basic stuff: 41 | 42 | Face recognition: 43 | 44 | ```r 45 | unconf <- ocv_read('https://jeroen.github.io/images/unconf18.jpg') 46 | faces <- ocv_face(unconf) 47 | ocv_write(faces, 'faces.jpg') 48 | ``` 49 | 50 | Or get the face location data: 51 | 52 | ```r 53 | facemask <- ocv_facemask(unconf) 54 | attr(facemask, 'faces') 55 | ``` 56 | 57 | ## Live Webcam Examples 58 | 59 | Live face detection: 60 | 61 | ```r 62 | library(opencv) 63 | ocv_video(ocv_face) 64 | ``` 65 | 66 | Edge detection: 67 | 68 | ```r 69 | library(opencv) 70 | ocv_video(ocv_edges) 71 | ``` 72 | 73 | ## Combine with Graphics 74 | 75 | Replaces the background with a plot: 76 | 77 | ```r 78 | library(opencv) 79 | library(ggplot2) 80 | 81 | # get webcam size 82 | test <- ocv_picture() 83 | bitmap <- ocv_bitmap(test) 84 | width <- dim(bitmap)[2] 85 | height <- dim(bitmap)[3] 86 | 87 | png('bg.png', width = width, height = height) 88 | par(ask=FALSE) 89 | print(ggplot2::qplot(speed, dist, data = cars, geom = c("smooth", "point"))) 90 | dev.off() 91 | bg <- ocv_read('bg.png') 92 | unlink('pg.png') 93 | ocv_video(function(input){ 94 | mask <- ocv_mog2(input) 95 | return(ocv_copyto(input, bg, mask)) 96 | }) 97 | ``` 98 | 99 | Put your face in the plot: 100 | 101 | ```r 102 | # Overlay face filter 103 | ocv_video(function(input){ 104 | mask <- ocv_facemask(input) 105 | ocv_copyto(input, bg, mask) 106 | }) 107 | ``` 108 | 109 | ## Live Face Survey 110 | 111 | Go stand on the left if you're a tidier 112 | 113 | ```r 114 | library(opencv) 115 | 116 | # get webcam size 117 | test <- ocv_picture() 118 | bitmap <- ocv_bitmap(test) 119 | width <- dim(bitmap)[2] 120 | height <- dim(bitmap)[3] 121 | 122 | # generates the plot 123 | makeplot <- function(x){ 124 | png('bg.png', width = width, height = height, res = 96) 125 | on.exit(unlink('bg.png')) 126 | groups <- seq(0, width, length.out = 4) 127 | left <- rep("left", sum(x < groups[2])) 128 | middle <- rep("middle", sum(x >= groups[2] & x < groups[3])) 129 | right <- rep("right", sum(x >= groups[3])) 130 | f <- factor(c(left, middle, right), levels = c('left', 'middle', 'right'), 131 | labels = c("Tidy!", "Whatever Works", "Base!")) 132 | color = I(c("#F1BB7B", "#FD6467", "#5B1A18")) 133 | plot(f, ylim = c(0, 5), 134 | main = "Are you a tidyer or baser?", col = color) 135 | dev.off() 136 | ocv_read('bg.png') 137 | } 138 | 139 | # overlays faces on the plot 140 | ocv_video(function(input){ 141 | mask <- ocv_facemask(input) 142 | faces <- attr(mask, 'faces') 143 | bg <- makeplot(faces$x) 144 | return(ocv_copyto(input, bg, mask)) 145 | }) 146 | ``` 147 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Anticonf (tm) script by Jeroen Ooms (2020) 3 | PKG_CONFIG_NAME="opencv4" 4 | PKG_CONFIG_NAME_ALT="opencv" 5 | PKG_DEB_NAME="libopencv-dev" 6 | PKG_RPM_NAME="opencv-devel" 7 | PKG_BREW_NAME="opencv" 8 | PKG_TEST_HEADER="" 9 | PKG_TEST_HEADER_XFEATURES2D="" 10 | PKG_LIBS="-lopencv_{stitching,superres,videostab,aruco,bgsegm,bioinspired,ccalib,dnn_objdetect,\ 11 | dpm,face,photo,fuzzy,hfs,img_hash,line_descriptor,optflow,reg,rgbd,saliency,stereo,structured_light,\ 12 | phase_unwrapping,surface_matching,tracking,datasets,dnn,plot,xfeatures2d,shape,video,ml,ximgproc,\ 13 | calib3d,features2d,highgui,videoio,flann,xobjdetect,imgcodecs,objdetect,xphoto,imgproc,core}" 14 | 15 | # For debugging opencv3 in macos: 16 | #export PKG_CONFIG_PATH="/usr/local/opt/opencv@3/lib/pkgconfig" 17 | 18 | # Use pkg-config if available 19 | PCVERSION=`pkg-config --version 2>/dev/null` 20 | if [ $? -eq 0 ]; then 21 | echo "This is pkg-config $PCVERSION" 22 | if pkg-config --exists ${PKG_CONFIG_NAME} ; then 23 | PKGCONFIG_CFLAGS=`pkg-config --cflags ${PKG_CONFIG_NAME}` 24 | PKGCONFIG_LIBS=`pkg-config --libs ${PKG_CONFIG_NAME}` 25 | PKGCONFIG_PREFIX=`pkg-config --variable=prefix ${PKG_CONFIG_NAME}` 26 | elif pkg-config --exists ${PKG_CONFIG_NAME_ALT}; then 27 | PKGCONFIG_CFLAGS=`pkg-config --cflags ${PKG_CONFIG_NAME_ALT}` 28 | PKGCONFIG_LIBS=`pkg-config --libs ${PKG_CONFIG_NAME_ALT}` 29 | PKGCONFIG_PREFIX=`pkg-config --variable=prefix ${PKG_CONFIG_NAME_ALT}` 30 | fi 31 | fi 32 | 33 | # Note that cflags may be empty in case of success 34 | if [ "$PKGCONFIG_CFLAGS" ] || [ "$PKGCONFIG_LIBS" ]; then 35 | echo "Found pkg-config cflags and libs!" 36 | PKG_CFLAGS=${PKGCONFIG_CFLAGS} 37 | PKG_LIBS=${PKGCONFIG_LIBS} 38 | if [ "$PKGCONFIG_PREFIX" ]; then 39 | PKG_CFLAGS="$PKG_CFLAGS -D_DATA_PREFIX=${PKGCONFIG_PREFIX}" 40 | fi 41 | elif [ `uname` = "Darwin" ]; then 42 | test ! "$CI" && brew --version 2>/dev/null 43 | if [ $? -eq 0 ]; then 44 | BREWDIR=`brew --prefix` 45 | PKG_CFLAGS="-I$BREWDIR/opt/opencv/include" 46 | PKG_LIBS="-L$BREWDIR/opt/opencv/lib $PKG_LIBS" 47 | else 48 | curl -sfL "https://autobrew.github.io/scripts/opencv" > autobrew 49 | . ./autobrew 50 | fi 51 | fi 52 | 53 | # For debugging 54 | echo "Using PKG_CFLAGS=$PKG_CFLAGS" 55 | echo "Using PKG_LIBS=$PKG_LIBS" 56 | 57 | # Use CXX17 if available (preferred for recent opencv) 58 | CXX17=`${R_HOME}/bin/R CMD config CXX17` || unset CXX17 59 | 60 | if [ "$CXX17" ]; then 61 | echo "Found C++17 compiler: $CXX17" 62 | CXXVER=CXX17 63 | else 64 | echo "Using C++11 compiler" 65 | CXXVER=CXX11 66 | fi 67 | 68 | CXX=$($R_HOME/bin/R CMD config ${CXXVER}) 69 | CXXSTD=$($R_HOME/bin/R CMD config ${CXXVER}STD) 70 | CXXFLAGS="$($R_HOME/bin/R CMD config ${CXXVER}FLAGS)" 71 | CPPFLAGS="$($R_HOME/bin/R CMD config CPPFLAGS)" 72 | CXXCPP="$CXX $CXXSTD -E" 73 | 74 | # Test configuration 75 | echo "#include $PKG_TEST_HEADER" | ${CXXCPP} ${CPPFLAGS} ${PKG_CFLAGS} ${CXXFLAGS} -xc++ - >/dev/null 2>configure.log 76 | 77 | if [ $? -ne 0 ]; then 78 | echo "-----------------------------[ ANTICONF ]-------------------------------" 79 | echo "Configuration failed to find $PKG_CONFIG_NAME library. Try installing:" 80 | echo " * deb: $PKG_DEB_NAME (Debian, Ubuntu, etc)" 81 | echo " * rpm: $PKG_RPM_NAME (Fedora, CentOS, RHEL)" 82 | echo " * brew: $PKG_BREW_NAME (Mac OSX)" 83 | echo "If $PKG_CONFIG_NAME is already installed, check that 'pkg-config' is in your" 84 | echo "PATH and PKG_CONFIG_PATH contains a $PKG_CONFIG_NAME.pc file." 85 | echo "---------------------------[ ERROR MESSAGE ]----------------------------" 86 | cat configure.log 87 | echo "------------------------------------------------------------------------" 88 | exit 1 89 | fi 90 | 91 | echo "#include $PKG_TEST_HEADER_XFEATURES2D" | ${CXXCPP} ${CPPFLAGS} ${PKG_CFLAGS} ${CXXFLAGS} -xc++ - >/dev/null 2>>configure.log 92 | if [ $? -ne 0 ]; then 93 | echo "Module $PKG_TEST_HEADER_XFEATURES2D has not been found on your system, disabling keypoint detection." 94 | else 95 | PKG_CFLAGS="$PKG_CFLAGS -DHAVE_XFEATURES2D" 96 | fi 97 | 98 | # Write to Makevars 99 | sed -e "s|@cflags@|$PKG_CFLAGS|" -e "s|@libs@|$PKG_LIBS|" -e "s|CXX11|${CXXVER}|" src/Makevars.in > src/Makevars 100 | 101 | # Success 102 | exit 0 103 | -------------------------------------------------------------------------------- /R/opencv.R: -------------------------------------------------------------------------------- 1 | #' OpenCV Computer Vision 2 | #' 3 | #' Tools to experiment with computer vision algorithms. Use [ocv_read] and 4 | #' [ocv_write] to load/save images on disk, or use [ocv_picture] / [ocv_video] 5 | #' to use your webcam. In RSudio IDE the image objects will automatically be 6 | #' displayed in the viewer pane. 7 | #' 8 | #' @export 9 | #' @rdname opencv 10 | #' @importFrom Rcpp sourceCpp 11 | #' @useDynLib opencv 12 | #' @param path image file such as png or jpeg 13 | #' @examples # Silly example 14 | #' mona <- ocv_read('https://jeroen.github.io/images/monalisa.jpg') 15 | #' 16 | #' # Edge detection 17 | #' ocv_edges(mona) 18 | #' ocv_markers(mona) 19 | #' 20 | #' # Find face 21 | #' faces <- ocv_face(mona) 22 | #' 23 | #' # To show locations of faces 24 | #' facemask <- ocv_facemask(mona) 25 | #' attr(facemask, 'faces') 26 | #' 27 | #' # This is not strictly needed 28 | #' ocv_destroy(mona) 29 | ocv_read <- function(path){ 30 | if(grepl("https?://", path)){ 31 | base <- basename(path) 32 | tmp <- file.path(tempdir(), base) 33 | utils::download.file(path, tmp, mode = 'wb') 34 | path <- tmp 35 | } 36 | path <- normalizePath(path, mustWork = TRUE) 37 | cvmat_read(path) 38 | } 39 | 40 | #' @export 41 | #' @rdname opencv 42 | #' @param image an ocv image object created from e.g. [ocv_read()] 43 | ocv_write <- function(image, path){ 44 | path <- normalizePath(path, mustWork = FALSE) 45 | cvmat_write(image, path) 46 | } 47 | 48 | #' @export 49 | #' @rdname opencv 50 | ocv_destroy <- function(image){ 51 | cvmat_destroy(image) 52 | } 53 | 54 | #' @export 55 | #' @rdname opencv 56 | ocv_bitmap <- function(image){ 57 | cvmat_bitmap(image) 58 | } 59 | 60 | #' @export 61 | #' @rdname opencv 62 | ocv_edges <- function(image){ 63 | cvmat_edges(image) 64 | } 65 | 66 | #' @export 67 | #' @rdname opencv 68 | ocv_picture <- function(){ 69 | cvmat_camera() 70 | } 71 | 72 | #' @export 73 | `print.opencv-image` <- function(x, ...){ 74 | viewer <- getOption("viewer") 75 | is_knit_image <- isTRUE(getOption('knitr.in.progress')) 76 | if(!is_knit_image && is.function(viewer) && !cvmat_dead(x)){ 77 | tmp <- file.path(tempdir(), paste0("preview.png")) 78 | ocv_write(x, path = tmp) 79 | viewer(tmp) 80 | } 81 | base::print.default(x) 82 | #TODO: copy from magick 83 | } 84 | 85 | #' @export 86 | #' @rdname opencv 87 | #' @param width output width in pixels 88 | #' @param height output height in pixels 89 | ocv_resize <- function(image, width = 0, height = 0){ 90 | cvmat_resize(image, as.integer(width), as.integer(height)) 91 | } 92 | 93 | #' @export 94 | #' @rdname opencv 95 | ocv_mog2 <- function(image){ 96 | cvmat_mog2(image) 97 | } 98 | 99 | #' @export 100 | #' @rdname opencv 101 | ocv_knn <- function(image){ 102 | cvmat_knn(image) 103 | } 104 | 105 | #' @export 106 | #' @rdname opencv 107 | ocv_hog <- function(image){ 108 | cvmat_hog(image) 109 | } 110 | 111 | #' @export 112 | #' @rdname opencv 113 | #' @param ksize size of blurring matrix 114 | ocv_blur <- function(image, ksize = 5){ 115 | cvmat_blur(image, ksize) 116 | } 117 | 118 | #' @export 119 | #' @rdname opencv 120 | #' @param color true or false 121 | ocv_sketch <- function(image, color = TRUE){ 122 | cvmat_sketch(image, color) 123 | } 124 | 125 | #' @export 126 | #' @rdname opencv 127 | ocv_stylize <- function(image){ 128 | cvmat_stylize(image) 129 | } 130 | 131 | #' @export 132 | #' @rdname opencv 133 | ocv_markers <- function(image){ 134 | cvmat_markers(image) 135 | } 136 | 137 | #' @export 138 | #' @rdname opencv 139 | ocv_info <- function(image){ 140 | info <- cvmat_info(image) 141 | info$type <- enum_label("type", info$type) 142 | info$depth <- enum_label("depth", info$depth) 143 | info 144 | } 145 | 146 | #' @export 147 | #' @rdname opencv 148 | #' @param target the output image 149 | #' @param mask only copy pixels from the mask 150 | ocv_copyto <- function(image, target, mask){ 151 | cvmat_copyto(image, target, mask) 152 | } 153 | 154 | #' @export 155 | #' @rdname opencv 156 | ocv_display <- function(image){ 157 | cvmat_display(image) 158 | } 159 | 160 | #' @export 161 | #' @rdname opencv 162 | #' @param filter an R function that takes and returns an opecv image 163 | #' @param stop_on_result stop if an object is detected 164 | ocv_video <- function(filter, stop_on_result = FALSE){ 165 | if(!is.function(filter)) 166 | stop("Filter must be a function") 167 | message("Starting video window (could be behind this window)") 168 | livestream(filter, stop_on_result) 169 | } 170 | 171 | #' @export 172 | #' @rdname opencv 173 | ocv_grayscale <- function(image){ 174 | cvmat_grayscale(image) 175 | } 176 | 177 | #' @export 178 | #' @rdname opencv 179 | ocv_version <- function(){ 180 | cvversion() 181 | } 182 | 183 | #' @importFrom magrittr %>% 184 | #' @export 185 | magrittr::`%>%` 186 | 187 | -------------------------------------------------------------------------------- /R/RcppExports.R: -------------------------------------------------------------------------------- 1 | # Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | cvmat_rect <- function(ptr, x = 0L, y = 0L, width = 0L, height = 0L) { 5 | .Call('_opencv_cvmat_rect', PACKAGE = 'opencv', ptr, x, y, width, height) 6 | } 7 | 8 | cvmat_bbox <- function(ptr) { 9 | .Call('_opencv_cvmat_bbox', PACKAGE = 'opencv', ptr) 10 | } 11 | 12 | cvpoints_bbox <- function(ptr, pts) { 13 | .Call('_opencv_cvpoints_bbox', PACKAGE = 'opencv', ptr, pts) 14 | } 15 | 16 | cvpoints_chull <- function(pts) { 17 | .Call('_opencv_cvpoints_chull', PACKAGE = 'opencv', pts) 18 | } 19 | 20 | cvmat_polygon <- function(ptr, pts, convex = FALSE, crop = FALSE, color = 255L) { 21 | .Call('_opencv_cvmat_polygon', PACKAGE = 'opencv', ptr, pts, convex, crop, color) 22 | } 23 | 24 | cvmat_destroy <- function(image) { 25 | invisible(.Call('_opencv_cvmat_destroy', PACKAGE = 'opencv', image)) 26 | } 27 | 28 | cvmat_dead <- function(image) { 29 | .Call('_opencv_cvmat_dead', PACKAGE = 'opencv', image) 30 | } 31 | 32 | cvmat_size <- function(image) { 33 | .Call('_opencv_cvmat_size', PACKAGE = 'opencv', image) 34 | } 35 | 36 | cvmat_new <- function() { 37 | .Call('_opencv_cvmat_new', PACKAGE = 'opencv') 38 | } 39 | 40 | cvmat_dupe <- function(image) { 41 | .Call('_opencv_cvmat_dupe', PACKAGE = 'opencv', image) 42 | } 43 | 44 | cvmat_read <- function(path) { 45 | .Call('_opencv_cvmat_read', PACKAGE = 'opencv', path) 46 | } 47 | 48 | cvmat_camera <- function() { 49 | .Call('_opencv_cvmat_camera', PACKAGE = 'opencv') 50 | } 51 | 52 | cvmat_write <- function(image, path) { 53 | .Call('_opencv_cvmat_write', PACKAGE = 'opencv', image, path) 54 | } 55 | 56 | cvmat_resize <- function(ptr, width = 0L, height = 0L) { 57 | .Call('_opencv_cvmat_resize', PACKAGE = 'opencv', ptr, width, height) 58 | } 59 | 60 | cvmat_raw_bgr <- function(image, width = 0L, height = 0L) { 61 | .Call('_opencv_cvmat_raw_bgr', PACKAGE = 'opencv', image, width, height) 62 | } 63 | 64 | cvmat_raw_bw <- function(image, width = 0L, height = 0L) { 65 | .Call('_opencv_cvmat_raw_bw', PACKAGE = 'opencv', image, width, height) 66 | } 67 | 68 | cvmat_bitmap <- function(ptr) { 69 | .Call('_opencv_cvmat_bitmap', PACKAGE = 'opencv', ptr) 70 | } 71 | 72 | cvmat_copyto <- function(from, to, mask) { 73 | .Call('_opencv_cvmat_copyto', PACKAGE = 'opencv', from, to, mask) 74 | } 75 | 76 | cvmat_info <- function(image) { 77 | .Call('_opencv_cvmat_info', PACKAGE = 'opencv', image) 78 | } 79 | 80 | cvmat_display <- function(ptr) { 81 | invisible(.Call('_opencv_cvmat_display', PACKAGE = 'opencv', ptr)) 82 | } 83 | 84 | livestream <- function(filter, stop_on_result = FALSE) { 85 | .Call('_opencv_livestream', PACKAGE = 'opencv', filter, stop_on_result) 86 | } 87 | 88 | data_prefix <- function() { 89 | .Call('_opencv_data_prefix', PACKAGE = 'opencv') 90 | } 91 | 92 | set_num_threads <- function(n = 0L) { 93 | .Call('_opencv_set_num_threads', PACKAGE = 'opencv', n) 94 | } 95 | 96 | cvmat_grayscale <- function(src) { 97 | .Call('_opencv_cvmat_grayscale', PACKAGE = 'opencv', src) 98 | } 99 | 100 | cvmat_blur <- function(ptr, ksize) { 101 | .Call('_opencv_cvmat_blur', PACKAGE = 'opencv', ptr, ksize) 102 | } 103 | 104 | cvmat_sketch <- function(ptr, color) { 105 | .Call('_opencv_cvmat_sketch', PACKAGE = 'opencv', ptr, color) 106 | } 107 | 108 | cvmat_stylize <- function(ptr) { 109 | .Call('_opencv_cvmat_stylize', PACKAGE = 'opencv', ptr) 110 | } 111 | 112 | enums_types <- function(maximum = 4L) { 113 | .Call('_opencv_enums_types', PACKAGE = 'opencv', maximum) 114 | } 115 | 116 | enums_depth <- function() { 117 | .Call('_opencv_enums_depth', PACKAGE = 'opencv') 118 | } 119 | 120 | cvmat_face <- function(ptr, facedata, eyedata) { 121 | .Call('_opencv_cvmat_face', PACKAGE = 'opencv', ptr, facedata, eyedata) 122 | } 123 | 124 | cvmat_facemask <- function(ptr, facedata) { 125 | .Call('_opencv_cvmat_facemask', PACKAGE = 'opencv', ptr, facedata) 126 | } 127 | 128 | cvmat_mog2 <- function(ptr) { 129 | .Call('_opencv_cvmat_mog2', PACKAGE = 'opencv', ptr) 130 | } 131 | 132 | cvmat_knn <- function(ptr) { 133 | .Call('_opencv_cvmat_knn', PACKAGE = 'opencv', ptr) 134 | } 135 | 136 | cvmat_edges <- function(ptr) { 137 | .Call('_opencv_cvmat_edges', PACKAGE = 'opencv', ptr) 138 | } 139 | 140 | cvkeypoints_fast <- function(ptr, threshold = 0L, nonmaxSuppression = TRUE, type = 2L) { 141 | .Call('_opencv_cvkeypoints_fast', PACKAGE = 'opencv', ptr, threshold, nonmaxSuppression, type) 142 | } 143 | 144 | cvkeypoints_harris <- function(ptr, numOctaves = 6L, corn_thresh = 0.01, DOG_thresh = 0.01, maxCorners = 5000L, num_layers = 4L) { 145 | .Call('_opencv_cvkeypoints_harris', PACKAGE = 'opencv', ptr, numOctaves, corn_thresh, DOG_thresh, maxCorners, num_layers) 146 | } 147 | 148 | cvmat_hog <- function(ptr) { 149 | .Call('_opencv_cvmat_hog', PACKAGE = 'opencv', ptr) 150 | } 151 | 152 | cvmat_markers <- function(ptr) { 153 | .Call('_opencv_cvmat_markers', PACKAGE = 'opencv', ptr) 154 | } 155 | 156 | cvmat_qr_detect <- function(ptr, return_image = FALSE, use_wechat = TRUE) { 157 | .Call('_opencv_cvmat_qr_detect', PACKAGE = 'opencv', ptr, return_image, use_wechat) 158 | } 159 | 160 | cvversion <- function() { 161 | .Call('_opencv_cvversion', PACKAGE = 'opencv') 162 | } 163 | 164 | -------------------------------------------------------------------------------- /src/base.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | #define xstr(s) str(s) 4 | #define str(s) #s 5 | 6 | using namespace cv; 7 | 8 | void finalize_mat( cv::Mat * frame ){ 9 | delete frame; 10 | frame = NULL; 11 | } 12 | 13 | //assume ownership 14 | XPtrMat cvmat_xptr(cv::Mat *frame){ 15 | XPtrMat ptr(frame); 16 | ptr.attr("class") = Rcpp::CharacterVector::create("opencv-image"); 17 | return ptr; 18 | } 19 | 20 | //copy from stack to heap 21 | XPtrMat cvmat_xptr(cv::Mat orig){ 22 | cv::Mat * frame = new cv::Mat(); 23 | orig.copyTo(*frame); 24 | return cvmat_xptr(frame); 25 | } 26 | 27 | //opencv has internal refcount system 28 | cv::Mat get_mat(XPtrMat image){ 29 | if(!image.inherits("opencv-image")) 30 | throw std::runtime_error("Image is not a opencv-image object"); 31 | if(image.get() == NULL) 32 | throw std::runtime_error("Image has been destroyed"); 33 | return * image.get(); 34 | } 35 | 36 | // [[Rcpp::export]] 37 | void cvmat_destroy(XPtrMat image){ 38 | if(!image.inherits("opencv-image")) 39 | throw std::runtime_error("Image is not a opencv-image object"); 40 | image.release(); 41 | } 42 | 43 | // [[Rcpp::export]] 44 | bool cvmat_dead(XPtrMat image){ 45 | return image.get() == NULL; 46 | } 47 | 48 | // [[Rcpp::export]] 49 | int cvmat_size(XPtrMat image){ 50 | return image->channels(); 51 | } 52 | 53 | // [[Rcpp::export]] 54 | XPtrMat cvmat_new(){ 55 | cv::Mat * frame = new cv::Mat(); 56 | return cvmat_xptr(frame); 57 | } 58 | 59 | // [[Rcpp::export]] 60 | XPtrMat cvmat_dupe(XPtrMat image){ 61 | return cvmat_xptr(get_mat(image)); 62 | } 63 | 64 | // [[Rcpp::export]] 65 | XPtrMat cvmat_read(Rcpp::String path){ 66 | const cv::String filename(path); 67 | cv::Mat frame = imread(filename); 68 | if(frame.empty()) 69 | throw std::runtime_error("Failed to read file"); 70 | return cvmat_xptr(frame); 71 | } 72 | 73 | // [[Rcpp::export]] 74 | XPtrMat cvmat_camera(){ 75 | VideoCapture cap(0); 76 | if(!cap.isOpened()) 77 | throw std::runtime_error("Failed to start Camera"); 78 | Mat frame; 79 | cap >> frame; 80 | cap >> frame; 81 | cap.release(); 82 | return cvmat_xptr(frame); 83 | } 84 | 85 | // [[Rcpp::export]] 86 | std::string cvmat_write(XPtrMat image, std::string path){ 87 | const cv::String filename(path); 88 | imwrite(filename, get_mat(image)); 89 | return path; 90 | } 91 | 92 | // [[Rcpp::export]] 93 | XPtrMat cvmat_resize(XPtrMat ptr, int width = 0, int height = 0){ 94 | cv::Mat input = get_mat(ptr); 95 | if(!width && !height){ 96 | width = input.cols; 97 | height = input.rows; 98 | } else if(width && !height){ 99 | height = round(input.rows * (width / double(input.cols))); 100 | } else if(!width && height){ 101 | width = round(input.cols * (height / double(input.rows))); 102 | } 103 | cv::Mat output; 104 | cv::resize(input, output, cv::Size(width, height)); 105 | return cvmat_xptr(output); 106 | } 107 | 108 | // [[Rcpp::export]] 109 | XPtrMat cvmat_raw_bgr(Rcpp::RawVector image, int width = 0, int height = 0){ 110 | // 8bit Blue Green Red 111 | if(image.length() != width * height * 3){ 112 | throw std::runtime_error("cvmat_raw_bgr requires data with 3 channels"); 113 | } 114 | std::vector x = Rcpp::as>(image); 115 | cv::Mat output(height, width, CV_8UC3, x.data()); 116 | return cvmat_xptr(output); 117 | } 118 | 119 | 120 | // [[Rcpp::export]] 121 | XPtrMat cvmat_raw_bw(Rcpp::RawVector image, int width = 0, int height = 0){ 122 | // 8bit 1 channel (e.g. Black/White or Greyscale) 123 | if(image.length() != width * height * 1){ 124 | throw std::runtime_error("cvmat_raw_bw requires data with 1 channel (e.g. grey or just black/white)"); 125 | } 126 | std::vector x = Rcpp::as>(image); 127 | cv::Mat output(height, width, CV_8U, x.data()); 128 | return cvmat_xptr(output); 129 | } 130 | 131 | // [[Rcpp::export]] 132 | Rcpp::RawVector cvmat_bitmap(XPtrMat ptr){ 133 | cv::Mat output; 134 | cv::Mat input = get_mat(ptr); 135 | cvtColor(input, output, COLOR_BGR2RGB); 136 | size_t size = output.total(); 137 | size_t channels = output.channels(); 138 | Rcpp::RawVector res(size * channels); 139 | std::memcpy(res.begin(), output.datastart, size * channels); 140 | res.attr("dim") = Rcpp::NumericVector::create(channels, output.cols, output.rows); 141 | return res; 142 | } 143 | 144 | // [[Rcpp::export]] 145 | XPtrMat cvmat_copyto(XPtrMat from, XPtrMat to, XPtrMat mask) { 146 | XPtrMat out = cvmat_xptr(get_mat(to)); 147 | get_mat(from).copyTo(get_mat(out), get_mat(mask)); 148 | return out; 149 | } 150 | 151 | // [[Rcpp::export]] 152 | Rcpp::List cvmat_info(XPtrMat image){ 153 | return Rcpp::List::create( 154 | Rcpp::_["width"] = get_mat(image).cols, 155 | Rcpp::_["height"] = get_mat(image).rows, 156 | Rcpp::_["channels"] = get_mat(image).channels(), 157 | Rcpp::_["depth"] = get_mat(image).depth(), 158 | Rcpp::_["type"] = get_mat(image).type() 159 | ); 160 | } 161 | 162 | // [[Rcpp::export]] 163 | void cvmat_display(XPtrMat ptr){ 164 | namedWindow("mywindow", 1); 165 | imshow("mywindow", get_mat(ptr)); 166 | try { 167 | while(true) { 168 | if(waitKey(30) >= 0 || cv::getWindowProperty("mywindow", 0) < 0) 169 | break; 170 | Rcpp::checkUserInterrupt(); 171 | } 172 | } catch(Rcpp::internal::InterruptedException e) { } 173 | cv::destroyWindow("mywindow"); 174 | cv::waitKey(1); 175 | } 176 | 177 | static void stop_video(VideoCapture &cap){ 178 | cap.release(); 179 | cv::destroyWindow("mywindow"); 180 | cv::waitKey(1); 181 | } 182 | 183 | // [[Rcpp::export]] 184 | Rcpp::RObject livestream(Rcpp::Function filter, bool stop_on_result = false){ 185 | VideoCapture cap(0); 186 | if(!cap.isOpened()) 187 | throw std::runtime_error("Failed to open Camera"); 188 | Mat image; 189 | namedWindow("mywindow", 1); 190 | Rcpp::RObject out = R_NilValue; 191 | try { 192 | for(int i = 0;;i++) { 193 | cap >> image; 194 | Rcpp::RObject val = filter(cvmat_xptr(image)); 195 | if(stop_on_result){ 196 | if(val != R_NilValue){ 197 | out = val; 198 | stop_video(cap); 199 | break; 200 | } 201 | imshow("mywindow", image); 202 | } else { 203 | if(val.inherits("opencv-image")){ 204 | imshow("mywindow", get_mat(XPtrMat(val))); 205 | } else { 206 | REprintf("\rFilter function did not return opencv-image object. Showing input image. (%d)", i); 207 | imshow("mywindow", image); 208 | } 209 | } 210 | if(waitKey(30) >= 0 || cv::getWindowProperty("mywindow", 0) < 0) 211 | break; 212 | Rcpp::checkUserInterrupt(); 213 | } 214 | } catch(Rcpp::internal::InterruptedException e) { 215 | stop_video(cap); 216 | } catch(std::exception& e) { 217 | stop_video(cap); 218 | throw e; 219 | } 220 | return out; 221 | } 222 | 223 | // [[Rcpp::export]] 224 | Rcpp::String data_prefix(){ 225 | #ifdef _DATA_PREFIX 226 | return Rcpp::String(xstr(_DATA_PREFIX)); 227 | #endif 228 | return Rcpp::String("/usr"); 229 | } 230 | 231 | // [[Rcpp::export]] 232 | int set_num_threads(int n = 0){ 233 | if(n > 0) 234 | setNumThreads(n); 235 | return getNumThreads(); 236 | } 237 | -------------------------------------------------------------------------------- /src/RcppExports.cpp: -------------------------------------------------------------------------------- 1 | // Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #include "opencv_types.h" 5 | #include 6 | 7 | using namespace Rcpp; 8 | 9 | #ifdef RCPP_USE_GLOBAL_ROSTREAM 10 | Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); 11 | Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); 12 | #endif 13 | 14 | // cvmat_rect 15 | XPtrMat cvmat_rect(XPtrMat ptr, int x, int y, int width, int height); 16 | RcppExport SEXP _opencv_cvmat_rect(SEXP ptrSEXP, SEXP xSEXP, SEXP ySEXP, SEXP widthSEXP, SEXP heightSEXP) { 17 | BEGIN_RCPP 18 | Rcpp::RObject rcpp_result_gen; 19 | Rcpp::RNGScope rcpp_rngScope_gen; 20 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 21 | Rcpp::traits::input_parameter< int >::type x(xSEXP); 22 | Rcpp::traits::input_parameter< int >::type y(ySEXP); 23 | Rcpp::traits::input_parameter< int >::type width(widthSEXP); 24 | Rcpp::traits::input_parameter< int >::type height(heightSEXP); 25 | rcpp_result_gen = Rcpp::wrap(cvmat_rect(ptr, x, y, width, height)); 26 | return rcpp_result_gen; 27 | END_RCPP 28 | } 29 | // cvmat_bbox 30 | XPtrMat cvmat_bbox(XPtrMat ptr); 31 | RcppExport SEXP _opencv_cvmat_bbox(SEXP ptrSEXP) { 32 | BEGIN_RCPP 33 | Rcpp::RObject rcpp_result_gen; 34 | Rcpp::RNGScope rcpp_rngScope_gen; 35 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 36 | rcpp_result_gen = Rcpp::wrap(cvmat_bbox(ptr)); 37 | return rcpp_result_gen; 38 | END_RCPP 39 | } 40 | // cvpoints_bbox 41 | XPtrMat cvpoints_bbox(XPtrMat ptr, Rcpp::List pts); 42 | RcppExport SEXP _opencv_cvpoints_bbox(SEXP ptrSEXP, SEXP ptsSEXP) { 43 | BEGIN_RCPP 44 | Rcpp::RObject rcpp_result_gen; 45 | Rcpp::RNGScope rcpp_rngScope_gen; 46 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 47 | Rcpp::traits::input_parameter< Rcpp::List >::type pts(ptsSEXP); 48 | rcpp_result_gen = Rcpp::wrap(cvpoints_bbox(ptr, pts)); 49 | return rcpp_result_gen; 50 | END_RCPP 51 | } 52 | // cvpoints_chull 53 | Rcpp::List cvpoints_chull(Rcpp::List pts); 54 | RcppExport SEXP _opencv_cvpoints_chull(SEXP ptsSEXP) { 55 | BEGIN_RCPP 56 | Rcpp::RObject rcpp_result_gen; 57 | Rcpp::RNGScope rcpp_rngScope_gen; 58 | Rcpp::traits::input_parameter< Rcpp::List >::type pts(ptsSEXP); 59 | rcpp_result_gen = Rcpp::wrap(cvpoints_chull(pts)); 60 | return rcpp_result_gen; 61 | END_RCPP 62 | } 63 | // cvmat_polygon 64 | XPtrMat cvmat_polygon(XPtrMat ptr, Rcpp::List pts, bool convex, bool crop, int color); 65 | RcppExport SEXP _opencv_cvmat_polygon(SEXP ptrSEXP, SEXP ptsSEXP, SEXP convexSEXP, SEXP cropSEXP, SEXP colorSEXP) { 66 | BEGIN_RCPP 67 | Rcpp::RObject rcpp_result_gen; 68 | Rcpp::RNGScope rcpp_rngScope_gen; 69 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 70 | Rcpp::traits::input_parameter< Rcpp::List >::type pts(ptsSEXP); 71 | Rcpp::traits::input_parameter< bool >::type convex(convexSEXP); 72 | Rcpp::traits::input_parameter< bool >::type crop(cropSEXP); 73 | Rcpp::traits::input_parameter< int >::type color(colorSEXP); 74 | rcpp_result_gen = Rcpp::wrap(cvmat_polygon(ptr, pts, convex, crop, color)); 75 | return rcpp_result_gen; 76 | END_RCPP 77 | } 78 | // cvmat_destroy 79 | void cvmat_destroy(XPtrMat image); 80 | RcppExport SEXP _opencv_cvmat_destroy(SEXP imageSEXP) { 81 | BEGIN_RCPP 82 | Rcpp::RNGScope rcpp_rngScope_gen; 83 | Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); 84 | cvmat_destroy(image); 85 | return R_NilValue; 86 | END_RCPP 87 | } 88 | // cvmat_dead 89 | bool cvmat_dead(XPtrMat image); 90 | RcppExport SEXP _opencv_cvmat_dead(SEXP imageSEXP) { 91 | BEGIN_RCPP 92 | Rcpp::RObject rcpp_result_gen; 93 | Rcpp::RNGScope rcpp_rngScope_gen; 94 | Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); 95 | rcpp_result_gen = Rcpp::wrap(cvmat_dead(image)); 96 | return rcpp_result_gen; 97 | END_RCPP 98 | } 99 | // cvmat_size 100 | int cvmat_size(XPtrMat image); 101 | RcppExport SEXP _opencv_cvmat_size(SEXP imageSEXP) { 102 | BEGIN_RCPP 103 | Rcpp::RObject rcpp_result_gen; 104 | Rcpp::RNGScope rcpp_rngScope_gen; 105 | Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); 106 | rcpp_result_gen = Rcpp::wrap(cvmat_size(image)); 107 | return rcpp_result_gen; 108 | END_RCPP 109 | } 110 | // cvmat_new 111 | XPtrMat cvmat_new(); 112 | RcppExport SEXP _opencv_cvmat_new() { 113 | BEGIN_RCPP 114 | Rcpp::RObject rcpp_result_gen; 115 | Rcpp::RNGScope rcpp_rngScope_gen; 116 | rcpp_result_gen = Rcpp::wrap(cvmat_new()); 117 | return rcpp_result_gen; 118 | END_RCPP 119 | } 120 | // cvmat_dupe 121 | XPtrMat cvmat_dupe(XPtrMat image); 122 | RcppExport SEXP _opencv_cvmat_dupe(SEXP imageSEXP) { 123 | BEGIN_RCPP 124 | Rcpp::RObject rcpp_result_gen; 125 | Rcpp::RNGScope rcpp_rngScope_gen; 126 | Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); 127 | rcpp_result_gen = Rcpp::wrap(cvmat_dupe(image)); 128 | return rcpp_result_gen; 129 | END_RCPP 130 | } 131 | // cvmat_read 132 | XPtrMat cvmat_read(Rcpp::String path); 133 | RcppExport SEXP _opencv_cvmat_read(SEXP pathSEXP) { 134 | BEGIN_RCPP 135 | Rcpp::RObject rcpp_result_gen; 136 | Rcpp::RNGScope rcpp_rngScope_gen; 137 | Rcpp::traits::input_parameter< Rcpp::String >::type path(pathSEXP); 138 | rcpp_result_gen = Rcpp::wrap(cvmat_read(path)); 139 | return rcpp_result_gen; 140 | END_RCPP 141 | } 142 | // cvmat_camera 143 | XPtrMat cvmat_camera(); 144 | RcppExport SEXP _opencv_cvmat_camera() { 145 | BEGIN_RCPP 146 | Rcpp::RObject rcpp_result_gen; 147 | Rcpp::RNGScope rcpp_rngScope_gen; 148 | rcpp_result_gen = Rcpp::wrap(cvmat_camera()); 149 | return rcpp_result_gen; 150 | END_RCPP 151 | } 152 | // cvmat_write 153 | std::string cvmat_write(XPtrMat image, std::string path); 154 | RcppExport SEXP _opencv_cvmat_write(SEXP imageSEXP, SEXP pathSEXP) { 155 | BEGIN_RCPP 156 | Rcpp::RObject rcpp_result_gen; 157 | Rcpp::RNGScope rcpp_rngScope_gen; 158 | Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); 159 | Rcpp::traits::input_parameter< std::string >::type path(pathSEXP); 160 | rcpp_result_gen = Rcpp::wrap(cvmat_write(image, path)); 161 | return rcpp_result_gen; 162 | END_RCPP 163 | } 164 | // cvmat_resize 165 | XPtrMat cvmat_resize(XPtrMat ptr, int width, int height); 166 | RcppExport SEXP _opencv_cvmat_resize(SEXP ptrSEXP, SEXP widthSEXP, SEXP heightSEXP) { 167 | BEGIN_RCPP 168 | Rcpp::RObject rcpp_result_gen; 169 | Rcpp::RNGScope rcpp_rngScope_gen; 170 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 171 | Rcpp::traits::input_parameter< int >::type width(widthSEXP); 172 | Rcpp::traits::input_parameter< int >::type height(heightSEXP); 173 | rcpp_result_gen = Rcpp::wrap(cvmat_resize(ptr, width, height)); 174 | return rcpp_result_gen; 175 | END_RCPP 176 | } 177 | // cvmat_raw_bgr 178 | XPtrMat cvmat_raw_bgr(Rcpp::RawVector image, int width, int height); 179 | RcppExport SEXP _opencv_cvmat_raw_bgr(SEXP imageSEXP, SEXP widthSEXP, SEXP heightSEXP) { 180 | BEGIN_RCPP 181 | Rcpp::RObject rcpp_result_gen; 182 | Rcpp::RNGScope rcpp_rngScope_gen; 183 | Rcpp::traits::input_parameter< Rcpp::RawVector >::type image(imageSEXP); 184 | Rcpp::traits::input_parameter< int >::type width(widthSEXP); 185 | Rcpp::traits::input_parameter< int >::type height(heightSEXP); 186 | rcpp_result_gen = Rcpp::wrap(cvmat_raw_bgr(image, width, height)); 187 | return rcpp_result_gen; 188 | END_RCPP 189 | } 190 | // cvmat_raw_bw 191 | XPtrMat cvmat_raw_bw(Rcpp::RawVector image, int width, int height); 192 | RcppExport SEXP _opencv_cvmat_raw_bw(SEXP imageSEXP, SEXP widthSEXP, SEXP heightSEXP) { 193 | BEGIN_RCPP 194 | Rcpp::RObject rcpp_result_gen; 195 | Rcpp::RNGScope rcpp_rngScope_gen; 196 | Rcpp::traits::input_parameter< Rcpp::RawVector >::type image(imageSEXP); 197 | Rcpp::traits::input_parameter< int >::type width(widthSEXP); 198 | Rcpp::traits::input_parameter< int >::type height(heightSEXP); 199 | rcpp_result_gen = Rcpp::wrap(cvmat_raw_bw(image, width, height)); 200 | return rcpp_result_gen; 201 | END_RCPP 202 | } 203 | // cvmat_bitmap 204 | Rcpp::RawVector cvmat_bitmap(XPtrMat ptr); 205 | RcppExport SEXP _opencv_cvmat_bitmap(SEXP ptrSEXP) { 206 | BEGIN_RCPP 207 | Rcpp::RObject rcpp_result_gen; 208 | Rcpp::RNGScope rcpp_rngScope_gen; 209 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 210 | rcpp_result_gen = Rcpp::wrap(cvmat_bitmap(ptr)); 211 | return rcpp_result_gen; 212 | END_RCPP 213 | } 214 | // cvmat_copyto 215 | XPtrMat cvmat_copyto(XPtrMat from, XPtrMat to, XPtrMat mask); 216 | RcppExport SEXP _opencv_cvmat_copyto(SEXP fromSEXP, SEXP toSEXP, SEXP maskSEXP) { 217 | BEGIN_RCPP 218 | Rcpp::RObject rcpp_result_gen; 219 | Rcpp::RNGScope rcpp_rngScope_gen; 220 | Rcpp::traits::input_parameter< XPtrMat >::type from(fromSEXP); 221 | Rcpp::traits::input_parameter< XPtrMat >::type to(toSEXP); 222 | Rcpp::traits::input_parameter< XPtrMat >::type mask(maskSEXP); 223 | rcpp_result_gen = Rcpp::wrap(cvmat_copyto(from, to, mask)); 224 | return rcpp_result_gen; 225 | END_RCPP 226 | } 227 | // cvmat_info 228 | Rcpp::List cvmat_info(XPtrMat image); 229 | RcppExport SEXP _opencv_cvmat_info(SEXP imageSEXP) { 230 | BEGIN_RCPP 231 | Rcpp::RObject rcpp_result_gen; 232 | Rcpp::RNGScope rcpp_rngScope_gen; 233 | Rcpp::traits::input_parameter< XPtrMat >::type image(imageSEXP); 234 | rcpp_result_gen = Rcpp::wrap(cvmat_info(image)); 235 | return rcpp_result_gen; 236 | END_RCPP 237 | } 238 | // cvmat_display 239 | void cvmat_display(XPtrMat ptr); 240 | RcppExport SEXP _opencv_cvmat_display(SEXP ptrSEXP) { 241 | BEGIN_RCPP 242 | Rcpp::RNGScope rcpp_rngScope_gen; 243 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 244 | cvmat_display(ptr); 245 | return R_NilValue; 246 | END_RCPP 247 | } 248 | // livestream 249 | Rcpp::RObject livestream(Rcpp::Function filter, bool stop_on_result); 250 | RcppExport SEXP _opencv_livestream(SEXP filterSEXP, SEXP stop_on_resultSEXP) { 251 | BEGIN_RCPP 252 | Rcpp::RObject rcpp_result_gen; 253 | Rcpp::RNGScope rcpp_rngScope_gen; 254 | Rcpp::traits::input_parameter< Rcpp::Function >::type filter(filterSEXP); 255 | Rcpp::traits::input_parameter< bool >::type stop_on_result(stop_on_resultSEXP); 256 | rcpp_result_gen = Rcpp::wrap(livestream(filter, stop_on_result)); 257 | return rcpp_result_gen; 258 | END_RCPP 259 | } 260 | // data_prefix 261 | Rcpp::String data_prefix(); 262 | RcppExport SEXP _opencv_data_prefix() { 263 | BEGIN_RCPP 264 | Rcpp::RObject rcpp_result_gen; 265 | Rcpp::RNGScope rcpp_rngScope_gen; 266 | rcpp_result_gen = Rcpp::wrap(data_prefix()); 267 | return rcpp_result_gen; 268 | END_RCPP 269 | } 270 | // set_num_threads 271 | int set_num_threads(int n); 272 | RcppExport SEXP _opencv_set_num_threads(SEXP nSEXP) { 273 | BEGIN_RCPP 274 | Rcpp::RObject rcpp_result_gen; 275 | Rcpp::RNGScope rcpp_rngScope_gen; 276 | Rcpp::traits::input_parameter< int >::type n(nSEXP); 277 | rcpp_result_gen = Rcpp::wrap(set_num_threads(n)); 278 | return rcpp_result_gen; 279 | END_RCPP 280 | } 281 | // cvmat_grayscale 282 | XPtrMat cvmat_grayscale(XPtrMat src); 283 | RcppExport SEXP _opencv_cvmat_grayscale(SEXP srcSEXP) { 284 | BEGIN_RCPP 285 | Rcpp::RObject rcpp_result_gen; 286 | Rcpp::RNGScope rcpp_rngScope_gen; 287 | Rcpp::traits::input_parameter< XPtrMat >::type src(srcSEXP); 288 | rcpp_result_gen = Rcpp::wrap(cvmat_grayscale(src)); 289 | return rcpp_result_gen; 290 | END_RCPP 291 | } 292 | // cvmat_blur 293 | XPtrMat cvmat_blur(XPtrMat ptr, size_t ksize); 294 | RcppExport SEXP _opencv_cvmat_blur(SEXP ptrSEXP, SEXP ksizeSEXP) { 295 | BEGIN_RCPP 296 | Rcpp::RObject rcpp_result_gen; 297 | Rcpp::RNGScope rcpp_rngScope_gen; 298 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 299 | Rcpp::traits::input_parameter< size_t >::type ksize(ksizeSEXP); 300 | rcpp_result_gen = Rcpp::wrap(cvmat_blur(ptr, ksize)); 301 | return rcpp_result_gen; 302 | END_RCPP 303 | } 304 | // cvmat_sketch 305 | XPtrMat cvmat_sketch(XPtrMat ptr, bool color); 306 | RcppExport SEXP _opencv_cvmat_sketch(SEXP ptrSEXP, SEXP colorSEXP) { 307 | BEGIN_RCPP 308 | Rcpp::RObject rcpp_result_gen; 309 | Rcpp::RNGScope rcpp_rngScope_gen; 310 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 311 | Rcpp::traits::input_parameter< bool >::type color(colorSEXP); 312 | rcpp_result_gen = Rcpp::wrap(cvmat_sketch(ptr, color)); 313 | return rcpp_result_gen; 314 | END_RCPP 315 | } 316 | // cvmat_stylize 317 | XPtrMat cvmat_stylize(XPtrMat ptr); 318 | RcppExport SEXP _opencv_cvmat_stylize(SEXP ptrSEXP) { 319 | BEGIN_RCPP 320 | Rcpp::RObject rcpp_result_gen; 321 | Rcpp::RNGScope rcpp_rngScope_gen; 322 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 323 | rcpp_result_gen = Rcpp::wrap(cvmat_stylize(ptr)); 324 | return rcpp_result_gen; 325 | END_RCPP 326 | } 327 | // enums_types 328 | Rcpp::List enums_types(int maximum); 329 | RcppExport SEXP _opencv_enums_types(SEXP maximumSEXP) { 330 | BEGIN_RCPP 331 | Rcpp::RObject rcpp_result_gen; 332 | Rcpp::RNGScope rcpp_rngScope_gen; 333 | Rcpp::traits::input_parameter< int >::type maximum(maximumSEXP); 334 | rcpp_result_gen = Rcpp::wrap(enums_types(maximum)); 335 | return rcpp_result_gen; 336 | END_RCPP 337 | } 338 | // enums_depth 339 | Rcpp::List enums_depth(); 340 | RcppExport SEXP _opencv_enums_depth() { 341 | BEGIN_RCPP 342 | Rcpp::RObject rcpp_result_gen; 343 | Rcpp::RNGScope rcpp_rngScope_gen; 344 | rcpp_result_gen = Rcpp::wrap(enums_depth()); 345 | return rcpp_result_gen; 346 | END_RCPP 347 | } 348 | // cvmat_face 349 | XPtrMat cvmat_face(XPtrMat ptr, const char * facedata, const char * eyedata); 350 | RcppExport SEXP _opencv_cvmat_face(SEXP ptrSEXP, SEXP facedataSEXP, SEXP eyedataSEXP) { 351 | BEGIN_RCPP 352 | Rcpp::RObject rcpp_result_gen; 353 | Rcpp::RNGScope rcpp_rngScope_gen; 354 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 355 | Rcpp::traits::input_parameter< const char * >::type facedata(facedataSEXP); 356 | Rcpp::traits::input_parameter< const char * >::type eyedata(eyedataSEXP); 357 | rcpp_result_gen = Rcpp::wrap(cvmat_face(ptr, facedata, eyedata)); 358 | return rcpp_result_gen; 359 | END_RCPP 360 | } 361 | // cvmat_facemask 362 | XPtrMat cvmat_facemask(XPtrMat ptr, const char * facedata); 363 | RcppExport SEXP _opencv_cvmat_facemask(SEXP ptrSEXP, SEXP facedataSEXP) { 364 | BEGIN_RCPP 365 | Rcpp::RObject rcpp_result_gen; 366 | Rcpp::RNGScope rcpp_rngScope_gen; 367 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 368 | Rcpp::traits::input_parameter< const char * >::type facedata(facedataSEXP); 369 | rcpp_result_gen = Rcpp::wrap(cvmat_facemask(ptr, facedata)); 370 | return rcpp_result_gen; 371 | END_RCPP 372 | } 373 | // cvmat_mog2 374 | XPtrMat cvmat_mog2(XPtrMat ptr); 375 | RcppExport SEXP _opencv_cvmat_mog2(SEXP ptrSEXP) { 376 | BEGIN_RCPP 377 | Rcpp::RObject rcpp_result_gen; 378 | Rcpp::RNGScope rcpp_rngScope_gen; 379 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 380 | rcpp_result_gen = Rcpp::wrap(cvmat_mog2(ptr)); 381 | return rcpp_result_gen; 382 | END_RCPP 383 | } 384 | // cvmat_knn 385 | XPtrMat cvmat_knn(XPtrMat ptr); 386 | RcppExport SEXP _opencv_cvmat_knn(SEXP ptrSEXP) { 387 | BEGIN_RCPP 388 | Rcpp::RObject rcpp_result_gen; 389 | Rcpp::RNGScope rcpp_rngScope_gen; 390 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 391 | rcpp_result_gen = Rcpp::wrap(cvmat_knn(ptr)); 392 | return rcpp_result_gen; 393 | END_RCPP 394 | } 395 | // cvmat_edges 396 | XPtrMat cvmat_edges(XPtrMat ptr); 397 | RcppExport SEXP _opencv_cvmat_edges(SEXP ptrSEXP) { 398 | BEGIN_RCPP 399 | Rcpp::RObject rcpp_result_gen; 400 | Rcpp::RNGScope rcpp_rngScope_gen; 401 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 402 | rcpp_result_gen = Rcpp::wrap(cvmat_edges(ptr)); 403 | return rcpp_result_gen; 404 | END_RCPP 405 | } 406 | // cvkeypoints_fast 407 | Rcpp::List cvkeypoints_fast(XPtrMat ptr, int threshold, bool nonmaxSuppression, int type); 408 | RcppExport SEXP _opencv_cvkeypoints_fast(SEXP ptrSEXP, SEXP thresholdSEXP, SEXP nonmaxSuppressionSEXP, SEXP typeSEXP) { 409 | BEGIN_RCPP 410 | Rcpp::RObject rcpp_result_gen; 411 | Rcpp::RNGScope rcpp_rngScope_gen; 412 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 413 | Rcpp::traits::input_parameter< int >::type threshold(thresholdSEXP); 414 | Rcpp::traits::input_parameter< bool >::type nonmaxSuppression(nonmaxSuppressionSEXP); 415 | Rcpp::traits::input_parameter< int >::type type(typeSEXP); 416 | rcpp_result_gen = Rcpp::wrap(cvkeypoints_fast(ptr, threshold, nonmaxSuppression, type)); 417 | return rcpp_result_gen; 418 | END_RCPP 419 | } 420 | // cvkeypoints_harris 421 | Rcpp::List cvkeypoints_harris(XPtrMat ptr, int numOctaves, float corn_thresh, float DOG_thresh, int maxCorners, int num_layers); 422 | RcppExport SEXP _opencv_cvkeypoints_harris(SEXP ptrSEXP, SEXP numOctavesSEXP, SEXP corn_threshSEXP, SEXP DOG_threshSEXP, SEXP maxCornersSEXP, SEXP num_layersSEXP) { 423 | BEGIN_RCPP 424 | Rcpp::RObject rcpp_result_gen; 425 | Rcpp::RNGScope rcpp_rngScope_gen; 426 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 427 | Rcpp::traits::input_parameter< int >::type numOctaves(numOctavesSEXP); 428 | Rcpp::traits::input_parameter< float >::type corn_thresh(corn_threshSEXP); 429 | Rcpp::traits::input_parameter< float >::type DOG_thresh(DOG_threshSEXP); 430 | Rcpp::traits::input_parameter< int >::type maxCorners(maxCornersSEXP); 431 | Rcpp::traits::input_parameter< int >::type num_layers(num_layersSEXP); 432 | rcpp_result_gen = Rcpp::wrap(cvkeypoints_harris(ptr, numOctaves, corn_thresh, DOG_thresh, maxCorners, num_layers)); 433 | return rcpp_result_gen; 434 | END_RCPP 435 | } 436 | // cvmat_hog 437 | XPtrMat cvmat_hog(XPtrMat ptr); 438 | RcppExport SEXP _opencv_cvmat_hog(SEXP ptrSEXP) { 439 | BEGIN_RCPP 440 | Rcpp::RObject rcpp_result_gen; 441 | Rcpp::RNGScope rcpp_rngScope_gen; 442 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 443 | rcpp_result_gen = Rcpp::wrap(cvmat_hog(ptr)); 444 | return rcpp_result_gen; 445 | END_RCPP 446 | } 447 | // cvmat_markers 448 | XPtrMat cvmat_markers(XPtrMat ptr); 449 | RcppExport SEXP _opencv_cvmat_markers(SEXP ptrSEXP) { 450 | BEGIN_RCPP 451 | Rcpp::RObject rcpp_result_gen; 452 | Rcpp::RNGScope rcpp_rngScope_gen; 453 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 454 | rcpp_result_gen = Rcpp::wrap(cvmat_markers(ptr)); 455 | return rcpp_result_gen; 456 | END_RCPP 457 | } 458 | // cvmat_qr_detect 459 | SEXP cvmat_qr_detect(XPtrMat ptr, bool return_image, bool use_wechat); 460 | RcppExport SEXP _opencv_cvmat_qr_detect(SEXP ptrSEXP, SEXP return_imageSEXP, SEXP use_wechatSEXP) { 461 | BEGIN_RCPP 462 | Rcpp::RObject rcpp_result_gen; 463 | Rcpp::RNGScope rcpp_rngScope_gen; 464 | Rcpp::traits::input_parameter< XPtrMat >::type ptr(ptrSEXP); 465 | Rcpp::traits::input_parameter< bool >::type return_image(return_imageSEXP); 466 | Rcpp::traits::input_parameter< bool >::type use_wechat(use_wechatSEXP); 467 | rcpp_result_gen = Rcpp::wrap(cvmat_qr_detect(ptr, return_image, use_wechat)); 468 | return rcpp_result_gen; 469 | END_RCPP 470 | } 471 | // cvversion 472 | std::string cvversion(); 473 | RcppExport SEXP _opencv_cvversion() { 474 | BEGIN_RCPP 475 | Rcpp::RObject rcpp_result_gen; 476 | Rcpp::RNGScope rcpp_rngScope_gen; 477 | rcpp_result_gen = Rcpp::wrap(cvversion()); 478 | return rcpp_result_gen; 479 | END_RCPP 480 | } 481 | 482 | static const R_CallMethodDef CallEntries[] = { 483 | {"_opencv_cvmat_rect", (DL_FUNC) &_opencv_cvmat_rect, 5}, 484 | {"_opencv_cvmat_bbox", (DL_FUNC) &_opencv_cvmat_bbox, 1}, 485 | {"_opencv_cvpoints_bbox", (DL_FUNC) &_opencv_cvpoints_bbox, 2}, 486 | {"_opencv_cvpoints_chull", (DL_FUNC) &_opencv_cvpoints_chull, 1}, 487 | {"_opencv_cvmat_polygon", (DL_FUNC) &_opencv_cvmat_polygon, 5}, 488 | {"_opencv_cvmat_destroy", (DL_FUNC) &_opencv_cvmat_destroy, 1}, 489 | {"_opencv_cvmat_dead", (DL_FUNC) &_opencv_cvmat_dead, 1}, 490 | {"_opencv_cvmat_size", (DL_FUNC) &_opencv_cvmat_size, 1}, 491 | {"_opencv_cvmat_new", (DL_FUNC) &_opencv_cvmat_new, 0}, 492 | {"_opencv_cvmat_dupe", (DL_FUNC) &_opencv_cvmat_dupe, 1}, 493 | {"_opencv_cvmat_read", (DL_FUNC) &_opencv_cvmat_read, 1}, 494 | {"_opencv_cvmat_camera", (DL_FUNC) &_opencv_cvmat_camera, 0}, 495 | {"_opencv_cvmat_write", (DL_FUNC) &_opencv_cvmat_write, 2}, 496 | {"_opencv_cvmat_resize", (DL_FUNC) &_opencv_cvmat_resize, 3}, 497 | {"_opencv_cvmat_raw_bgr", (DL_FUNC) &_opencv_cvmat_raw_bgr, 3}, 498 | {"_opencv_cvmat_raw_bw", (DL_FUNC) &_opencv_cvmat_raw_bw, 3}, 499 | {"_opencv_cvmat_bitmap", (DL_FUNC) &_opencv_cvmat_bitmap, 1}, 500 | {"_opencv_cvmat_copyto", (DL_FUNC) &_opencv_cvmat_copyto, 3}, 501 | {"_opencv_cvmat_info", (DL_FUNC) &_opencv_cvmat_info, 1}, 502 | {"_opencv_cvmat_display", (DL_FUNC) &_opencv_cvmat_display, 1}, 503 | {"_opencv_livestream", (DL_FUNC) &_opencv_livestream, 2}, 504 | {"_opencv_data_prefix", (DL_FUNC) &_opencv_data_prefix, 0}, 505 | {"_opencv_set_num_threads", (DL_FUNC) &_opencv_set_num_threads, 1}, 506 | {"_opencv_cvmat_grayscale", (DL_FUNC) &_opencv_cvmat_grayscale, 1}, 507 | {"_opencv_cvmat_blur", (DL_FUNC) &_opencv_cvmat_blur, 2}, 508 | {"_opencv_cvmat_sketch", (DL_FUNC) &_opencv_cvmat_sketch, 2}, 509 | {"_opencv_cvmat_stylize", (DL_FUNC) &_opencv_cvmat_stylize, 1}, 510 | {"_opencv_enums_types", (DL_FUNC) &_opencv_enums_types, 1}, 511 | {"_opencv_enums_depth", (DL_FUNC) &_opencv_enums_depth, 0}, 512 | {"_opencv_cvmat_face", (DL_FUNC) &_opencv_cvmat_face, 3}, 513 | {"_opencv_cvmat_facemask", (DL_FUNC) &_opencv_cvmat_facemask, 2}, 514 | {"_opencv_cvmat_mog2", (DL_FUNC) &_opencv_cvmat_mog2, 1}, 515 | {"_opencv_cvmat_knn", (DL_FUNC) &_opencv_cvmat_knn, 1}, 516 | {"_opencv_cvmat_edges", (DL_FUNC) &_opencv_cvmat_edges, 1}, 517 | {"_opencv_cvkeypoints_fast", (DL_FUNC) &_opencv_cvkeypoints_fast, 4}, 518 | {"_opencv_cvkeypoints_harris", (DL_FUNC) &_opencv_cvkeypoints_harris, 6}, 519 | {"_opencv_cvmat_hog", (DL_FUNC) &_opencv_cvmat_hog, 1}, 520 | {"_opencv_cvmat_markers", (DL_FUNC) &_opencv_cvmat_markers, 1}, 521 | {"_opencv_cvmat_qr_detect", (DL_FUNC) &_opencv_cvmat_qr_detect, 3}, 522 | {"_opencv_cvversion", (DL_FUNC) &_opencv_cvversion, 0}, 523 | {NULL, NULL, 0} 524 | }; 525 | 526 | RcppExport void R_init_opencv(DllInfo *dll) { 527 | R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); 528 | R_useDynamicSymbols(dll, FALSE); 529 | } 530 | --------------------------------------------------------------------------------