├── diego.jpg ├── go.mod ├── gocvx ├── cgo.go ├── gocvx.h ├── gocvx.cpp ├── gocvx.go ├── core.h ├── core.cpp └── core.go ├── .gitignore ├── README.md ├── example.go ├── LICENSE └── arcface ├── face_align.go ├── arcface.go ├── pre_process.go └── post_process.go /diego.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jack139/arcface-go/HEAD/diego.jpg -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/jack139/arcface-go 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/disintegration/imaging v1.6.2 7 | github.com/ivansuteja96/go-onnxruntime v0.0.0-20220724043122-8d5640cbb46b 8 | ) 9 | -------------------------------------------------------------------------------- /gocvx/cgo.go: -------------------------------------------------------------------------------- 1 | package gocvx 2 | 3 | /* 4 | #cgo !windows pkg-config: opencv4 5 | #cgo CXXFLAGS: --std=c++11 6 | #cgo !windows CPPFLAGS: -I/usr/local/include/opencv4 7 | #cgo !windows LDFLAGS: -L/usr/local/lib -lopencv_core -lopencv_calib3d -lopencv_imgproc 8 | */ 9 | import "C" 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # Binaries for programs and plugins 7 | *.exe 8 | *.exe~ 9 | *.dll 10 | *.so 11 | *.dylib 12 | 13 | # Test binary, build with `go test -c` 14 | *.test 15 | 16 | # Output of the go coverage tool, specifically when used with LiteIDE 17 | *.out 18 | 19 | # python compiled code 20 | *.pyc 21 | 22 | # mod.sum 23 | *.sum 24 | 25 | # built file path 26 | build/ 27 | outputs/ 28 | data/ -------------------------------------------------------------------------------- /gocvx/gocvx.h: -------------------------------------------------------------------------------- 1 | #ifndef _GOCVX_H_ 2 | #define _GOCVX_H_ 3 | 4 | #ifdef __cplusplus 5 | #include 6 | #include 7 | 8 | 9 | extern "C" { 10 | #endif 11 | 12 | #include "core.h" 13 | 14 | Mat EstimateAffinePartial2DWithParams(Point2fVector from, Point2fVector to, Mat inliers, int method, double ransacReprojThreshold, size_t maxIters, double confidence, size_t refineIters); 15 | void WarpAffine(Mat src, Mat dst, Mat m, Size dsize); 16 | void CvtColor(Mat src, Mat dst, int code); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif //_GOCVX_H_ 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arcface-go 2 | 3 | Go implementation of Arcface inference 4 | 5 | 6 | 7 | ## Prerequisites 8 | 9 | - The onnx-format models used in the code is ["**buffalo_l**"](https://insightface.cn-sh2.ufileos.com/models/buffalo_l.zip) from [insightface](https://github.com/deepinsight/insightface/tree/master/model_zoo). 10 | - [ONNX Runtime](https://github.com/microsoft/onnxruntime) (v1.12.1 in my environment) is required. 11 | - [OpenCV](https://github.com/opencv/opencv) (v4.5.5 in my environment) is required, because some codes borrowed from [gocv](https://github.com/hybridgroup/gocv) to implement EstimateAffinePartial2DWithParams(). 12 | 13 | 14 | 15 | ## Run example 16 | 17 | The example is too simple, detect faces in the input image and retrieve features of the first face. 18 | 19 | ``` 20 | go run example.go 21 | ``` 22 | 23 | - If your ```onnxruntime``` and ```opencv``` is not installed in ```/usr/local```, some paths in CGO flags and ```LD_LIARARY_PATH``` should be corrected (CGO_CPPFLAGS="-I/path/to/include/opencv4" LD_LIBRARY_PATH=/path/to/lib ). 24 | - path to "**buffalo_l**" should be corrected in ```example.go``` . 25 | 26 | 27 | 28 | ## Sample API 29 | [arcface-go-api](https://github.com/jack139/arcface-go-api) 30 | -------------------------------------------------------------------------------- /example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | import ( 5 | "log" 6 | "github.com/disintegration/imaging" 7 | 8 | "github.com/jack139/arcface-go/arcface" 9 | ) 10 | 11 | const ( 12 | test_image_path = "diego.jpg" 13 | ) 14 | 15 | 16 | func main() { 17 | if err := arcface.LoadOnnxModel("../../cv/face_model/arcface/models/buffalo_l"); err!=nil { 18 | log.Fatal("Load model fail: ", err.Error()) 19 | } 20 | 21 | // load image 22 | srcImage, err := imaging.Open(test_image_path) 23 | if err != nil { 24 | log.Fatal("Open image error: ", err.Error()) 25 | } 26 | 27 | dets, kpss, err := arcface.FaceDetect(srcImage) 28 | if err != nil { 29 | log.Fatal("FaceDetect() error: ", err.Error()) 30 | } 31 | 32 | log.Println("face num: ", len(kpss)) 33 | 34 | if len(dets)==0 { 35 | log.Println("No face detected.") 36 | return 37 | } 38 | 39 | 40 | /* 41 | // crop face by detect boxes without normalization 42 | sr := image.Rectangle{ 43 | image.Point{int(dets[0][0]), int(dets[0][1])}, 44 | image.Point{int(dets[0][2]), int(dets[0][3])}, 45 | } 46 | src2 := imaging.Crop(srcImage, sr) 47 | _ = imaging.Save(src2, "crop_face.jpg") 48 | */ 49 | 50 | 51 | // just use the first face data, which score is the highest 52 | features, normFace, err := arcface.FaceFeatures(srcImage, kpss[0]) 53 | if err != nil { 54 | log.Fatal("FaceFeatures() error: %s\n", err.Error()) 55 | } 56 | 57 | // normalized face image 58 | _ = imaging.Save(normFace, "norm_face.jpg") 59 | 60 | log.Println("features: ", features) 61 | } 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022, Tao Guan. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 21 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 24 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /gocvx/gocvx.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "gocvx.h" 6 | 7 | /* 8 | // for test: print Point2fVector contents 9 | void printVVVVV(Point2fVector const &input) 10 | { 11 | for (int i = 0; i < input->size(); i++) { 12 | std::cerr << input->at(i) << ' '; 13 | } 14 | std::cerr << "\n"; 15 | } 16 | */ 17 | 18 | Mat EstimateAffinePartial2DWithParams(Point2fVector from, Point2fVector to, Mat inliers, int method, double ransacReprojThreshold, size_t maxIters, double confidence, size_t refineIters) { 19 | //printVVVVV(from); 20 | //printVVVVV(to); 21 | return new cv::Mat(cv::estimateAffinePartial2D(*from, *to, *inliers, method, ransacReprojThreshold, maxIters, confidence, refineIters)); 22 | } 23 | 24 | /* declaration in opencv 4.5.5 25 | CV_EXPORTS_W cv::Mat estimateAffinePartial2D(InputArray from, InputArray to, OutputArray inliers = noArray(), 26 | int method = RANSAC, double ransacReprojThreshold = 3, 27 | size_t maxIters = 2000, double confidence = 0.99, 28 | size_t refineIters = 10); 29 | */ 30 | 31 | 32 | void WarpAffine(Mat src, Mat dst, Mat m, Size dsize) { 33 | cv::Size sz(dsize.width, dsize.height); 34 | cv::warpAffine(*src, *dst, *m, sz); 35 | } 36 | 37 | /* declaration in opencv 4.5.5 38 | CV_EXPORTS_W void warpAffine( InputArray src, OutputArray dst, 39 | InputArray M, Size dsize, 40 | int flags = INTER_LINEAR, 41 | int borderMode = BORDER_CONSTANT, 42 | const Scalar& borderValue = Scalar()); 43 | */ 44 | 45 | void CvtColor(Mat src, Mat dst, int code) { 46 | cv::cvtColor(*src, *dst, code); 47 | } 48 | -------------------------------------------------------------------------------- /arcface/face_align.go: -------------------------------------------------------------------------------- 1 | package arcface 2 | 3 | import ( 4 | "fmt" 5 | "image" 6 | 7 | "github.com/jack139/arcface-go/gocvx" 8 | ) 9 | 10 | var ( 11 | // arcface matrix from insightface/utils/face_align.py 12 | arcface_src = []gocvx.Point2f{ 13 | {38.2946, 51.6963}, 14 | {73.5318, 51.5014}, 15 | {56.0252, 71.7366}, 16 | {41.5493, 92.3655}, 17 | {70.7299, 92.2041}, 18 | } 19 | ) 20 | 21 | 22 | // Crop face image and normalization 23 | func norm_crop(srcImage image.Image, lmk []float32) (image.Image, error) { 24 | // similarity transform 25 | m := estimate_norm(lmk) 26 | defer m.Close() 27 | 28 | // print out the 2×3 transformation matrix 29 | //printM(m) 30 | 31 | // transfer to Mat 32 | src, err := gocvx.ImageToMatRGB(srcImage) 33 | if err!=nil { 34 | return nil, err 35 | } 36 | 37 | dst := src.Clone() 38 | defer dst.Close() 39 | 40 | // affine transformation to an image (Mat) 41 | gocvx.WarpAffine(src, &dst, m, image.Point{face_align_image_size, face_align_image_size}) 42 | 43 | // Mat transfer to image 44 | aimg, err := dst.ToImage() 45 | if err!=nil { 46 | return nil, err 47 | } 48 | 49 | return aimg, nil 50 | } 51 | 52 | 53 | // equal to python: skimage.transform.SimilarityTransform() 54 | func estimate_norm(lmk []float32) gocvx.Mat { 55 | dst := make([]gocvx.Point2f, 5) 56 | for i:=0;i<5;i++ { 57 | dst[i] = gocvx.Point2f{lmk[i*2], lmk[i*2+1]} 58 | } 59 | 60 | pvsrc := gocvx.NewPoint2fVectorFromPoints(arcface_src) 61 | defer pvsrc.Close() 62 | 63 | pvdst := gocvx.NewPoint2fVectorFromPoints(dst) 64 | defer pvdst.Close() 65 | 66 | inliers := gocvx.NewMat() 67 | defer inliers.Close() 68 | method := 4 // cv2.LMEDS 69 | ransacProjThreshold := 3.0 70 | maxiters := uint(2000) 71 | confidence := 0.99 72 | refineIters := uint(10) 73 | 74 | m := gocvx.EstimateAffinePartial2DWithParams(pvdst, pvsrc, inliers, method, 75 | ransacProjThreshold, maxiters, confidence, refineIters) 76 | 77 | return m 78 | } 79 | 80 | // print matrix, for test 81 | func printM(m gocvx.Mat) { 82 | for i:=0;i 1 { // width > height 27 | newWidth = inputSize 28 | newHeight = int(float32(newWidth) / im_ratio) 29 | } else { 30 | newHeight = inputSize 31 | newWidth = int(float32(newHeight) * im_ratio) 32 | } 33 | 34 | result := imaging.Resize(src, newWidth, newHeight, imaging.Lanczos) 35 | result = padBox(result) 36 | 37 | rgbs := make([]float32, inputSize*inputSize*3) 38 | 39 | j := 0 40 | for i := range result.Pix { 41 | if (i+1)%4 != 0 { 42 | rgbs[j] = float32(result.Pix[i]) 43 | j++ 44 | } 45 | } 46 | 47 | rgbs = transposeRGB(rgbs) 48 | 49 | channelLength := len(rgbs) / 3 50 | for i := 0; i < channelLength; i++ { 51 | rgbs[i] = normalize(rgbs[i], 127.5, 128.0) 52 | rgbs[i+channelLength] = normalize(rgbs[i+channelLength], 127.5, 128.0) 53 | rgbs[i+channelLength*2] = normalize(rgbs[i+channelLength*2], 127.5, 128.0) 54 | } 55 | 56 | return rgbs, float32(newHeight) / float32(src.Bounds().Dy()) 57 | } 58 | 59 | 60 | func normalize(in float32, m float32, s float32) float32 { 61 | return (in - m) / s 62 | } 63 | 64 | 65 | // change image to square rect, padding with color Black 66 | func padBox(src image.Image) *image.NRGBA { 67 | var maxW int 68 | 69 | if src.Bounds().Dx() > src.Bounds().Dy() { 70 | maxW = src.Bounds().Dx() 71 | } else { 72 | maxW = src.Bounds().Dy() 73 | } 74 | 75 | dst := imaging.New(maxW, maxW, color.Black) 76 | dst = imaging.Paste(dst, src, image.Point{0,0}) 77 | 78 | //_ = imaging.Save(dst, "data/pading.jpg") 79 | 80 | return dst 81 | } 82 | 83 | // pre-process input data for face-features model 84 | func preprocessFace(src image.Image, inputSize int) ([]float32) { 85 | result := padBox(src) 86 | 87 | rgbs := make([]float32, inputSize*inputSize*3) 88 | 89 | j := 0 90 | for i := range result.Pix { 91 | if (i+1)%4 != 0 { 92 | rgbs[j] = float32(result.Pix[i]) 93 | j++ 94 | } 95 | } 96 | 97 | rgbs = transposeRGB(rgbs) 98 | 99 | channelLength := len(rgbs) / 3 100 | for i := 0; i < channelLength; i++ { 101 | rgbs[i] = normalize(rgbs[i], 127.5, 127.5) 102 | rgbs[i+channelLength] = normalize(rgbs[i+channelLength], 127.5, 127.5) 103 | rgbs[i+channelLength*2] = normalize(rgbs[i+channelLength*2], 127.5, 127.5) 104 | } 105 | 106 | return rgbs 107 | } 108 | -------------------------------------------------------------------------------- /gocvx/gocvx.go: -------------------------------------------------------------------------------- 1 | // Package to provide some OpenCV functions required in arcface inference. 2 | // Some codes are borrowed from Gocv. The EstimateAffinePartial2DWithParams() is implemented by self because Gocv do not have it. 3 | package gocvx 4 | 5 | /* 6 | #include 7 | #include "gocvx.h" 8 | */ 9 | import "C" 10 | import ( 11 | "image" 12 | "image/color" 13 | "errors" 14 | ) 15 | 16 | type ColorConversionCode int 17 | 18 | const ( 19 | // ColorBGRToRGBA converts from BGR to RGB with alpha channel. 20 | ColorBGRToRGBA ColorConversionCode = 2 21 | 22 | // ColorRGBAToBGR converts from RGB with alpha to BGR color space. 23 | ColorRGBAToBGR ColorConversionCode = 3 24 | 25 | // ColorBGRAToRGBA converts from BGR with alpha channel 26 | // to RGB with alpha channel. 27 | ColorBGRAToRGBA ColorConversionCode = 5 28 | ) 29 | 30 | 31 | // EstimateAffinePartial2D computes an optimal limited affine transformation 32 | // with 4 degrees of freedom between two 2D point sets. 33 | // 34 | // For further details, please see: 35 | // https://docs.opencv.org/master/d9/d0c/group__calib3d.html#gad767faff73e9cbd8b9d92b955b50062d 36 | // 37 | // Add more parameters to original gocv EstimateAffinePartial2D() 38 | func EstimateAffinePartial2DWithParams(from Point2fVector, to Point2fVector, inliers Mat, method int, ransacReprojThreshold float64, maxIters uint, confidence float64, refineIters uint) Mat { 39 | return newMat(C.EstimateAffinePartial2DWithParams(from.p, to.p, inliers.p, C.int(method), C.double(ransacReprojThreshold), C.size_t(maxIters), C.double(confidence), C.size_t(refineIters))) 40 | } 41 | 42 | 43 | // WarpAffine applies an affine transformation to an image. For more parameters please check WarpAffineWithParams 44 | // 45 | // For further details, please see: 46 | // https://docs.opencv.org/master/da/d54/group__imgproc__transform.html#ga0203d9ee5fcd28d40dbc4a1ea4451983 47 | func WarpAffine(src Mat, dst *Mat, m Mat, sz image.Point) { 48 | pSize := C.struct_Size{ 49 | width: C.int(sz.X), 50 | height: C.int(sz.Y), 51 | } 52 | 53 | C.WarpAffine(src.p, dst.p, m.p, pSize) 54 | } 55 | 56 | 57 | // ImageToMatRGB converts image.Image to gocv.Mat, 58 | // which represents RGB image having 8bit for each component. 59 | // Type of Mat is gocv.MatTypeCV8UC3. 60 | func ImageToMatRGB(img image.Image) (Mat, error) { 61 | bounds := img.Bounds() 62 | x := bounds.Dx() 63 | y := bounds.Dy() 64 | 65 | var data []uint8 66 | switch img.ColorModel() { 67 | case color.RGBAModel: 68 | m, res := img.(*image.RGBA) 69 | if true != res { 70 | return NewMat(), errors.New("Image color format error") 71 | } 72 | data = m.Pix 73 | // speed up the conversion process of RGBA format 74 | src, err := NewMatFromBytes(y, x, MatTypeCV8UC4, data) 75 | if err != nil { 76 | return NewMat(), err 77 | } 78 | defer src.Close() 79 | 80 | dst := NewMat() 81 | CvtColor(src, &dst, ColorRGBAToBGR) 82 | return dst, nil 83 | 84 | default: 85 | data := make([]byte, 0, x*y*3) 86 | for j := bounds.Min.Y; j < bounds.Max.Y; j++ { 87 | for i := bounds.Min.X; i < bounds.Max.X; i++ { 88 | r, g, b, _ := img.At(i, j).RGBA() 89 | data = append(data, byte(b>>8), byte(g>>8), byte(r>>8)) 90 | } 91 | } 92 | return NewMatFromBytes(y, x, MatTypeCV8UC3, data) 93 | } 94 | } 95 | 96 | // CvtColor converts an image from one color space to another. 97 | // It converts the src Mat image to the dst Mat using the 98 | // code param containing the desired ColorConversionCode color space. 99 | // 100 | // For further details, please see: 101 | // http://docs.opencv.org/master/d7/d1b/group__imgproc__misc.html#ga4e0972be5de079fed4e3a10e24ef5ef0 102 | // 103 | func CvtColor(src Mat, dst *Mat, code ColorConversionCode) { 104 | C.CvtColor(src.p, dst.p, C.int(code)) 105 | } 106 | 107 | 108 | // ToImage converts a Mat to a image.Image. 109 | func (m *Mat) ToImage() (image.Image, error) { 110 | switch m.Type() { 111 | case MatTypeCV8UC1: 112 | img := image.NewGray(image.Rect(0, 0, m.Cols(), m.Rows())) 113 | data, err := m.DataPtrUint8() 114 | if err != nil { 115 | return nil, err 116 | } 117 | copy(img.Pix, data[0:]) 118 | return img, nil 119 | 120 | case MatTypeCV8UC3: 121 | dst := NewMat() 122 | defer dst.Close() 123 | 124 | C.CvtColor(m.p, dst.p, C.int(ColorBGRToRGBA)) 125 | 126 | img := image.NewRGBA(image.Rect(0, 0, m.Cols(), m.Rows())) 127 | data, err := dst.DataPtrUint8() 128 | if err != nil { 129 | return nil, err 130 | } 131 | 132 | copy(img.Pix, data[0:]) 133 | return img, nil 134 | 135 | case MatTypeCV8UC4: 136 | dst := NewMat() 137 | defer dst.Close() 138 | 139 | C.CvtColor(m.p, dst.p, C.int(ColorBGRAToRGBA)) 140 | 141 | img := image.NewNRGBA(image.Rect(0, 0, m.Cols(), m.Rows())) 142 | data, err := dst.DataPtrUint8() 143 | if err != nil { 144 | return nil, err 145 | } 146 | copy(img.Pix, data[0:]) 147 | return img, nil 148 | 149 | default: 150 | return nil, errors.New("ToImage supports only MatType CV8UC1, CV8UC3 and CV8UC4") 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /arcface/post_process.go: -------------------------------------------------------------------------------- 1 | package arcface 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | 7 | "github.com/ivansuteja96/go-onnxruntime" 8 | ) 9 | 10 | const ( 11 | nms_thresh = float32(0.4) 12 | det_thresh = float32(0.5) 13 | ) 14 | 15 | var ( 16 | // len(outputs)==9 17 | _fmc = 3 18 | _feat_stride_fpn = []int{8, 16, 32} 19 | _num_anchors = 2 20 | ) 21 | 22 | // process result after face-detect model inferenced 23 | func processResult(net_outs []onnxruntime.TensorValue, det_scale float32) ([][]float32, [][]float32) { 24 | //for i:=0;idet_thresh { 77 | pos_inds = append(pos_inds, i) 78 | } 79 | } 80 | 81 | bboxes := distance2bbox(anchor_centers, bbox_preds) 82 | kpss := distance2kps(anchor_centers, kps_preds) 83 | 84 | for i:=range pos_inds { 85 | scores_list = append(scores_list, scores[pos_inds[i]]) 86 | bboxes_list = append(bboxes_list, bboxes[pos_inds[i]]) 87 | kpss_list = append(kpss_list, kpss[pos_inds[i]]) 88 | } 89 | } 90 | 91 | 92 | // post process after get boxes and landmarks 93 | 94 | for i := range bboxes_list { 95 | for j:=0;j<4;j++ { 96 | bboxes_list[i][j] /= det_scale 97 | } 98 | bboxes_list[i] = append(bboxes_list[i], scores_list[i]) 99 | 100 | for j:=0;j<10;j++ { 101 | kpss_list[i][j] /= det_scale 102 | } 103 | kpss_list[i] = append(kpss_list[i], scores_list[i]) 104 | } 105 | 106 | sort.Slice(bboxes_list, func(i, j int) bool { return bboxes_list[i][4] > bboxes_list[j][4] }) 107 | sort.Slice(kpss_list, func(i, j int) bool { return kpss_list[i][10] > kpss_list[j][10] }) 108 | 109 | keep := nms(bboxes_list) 110 | 111 | det := make([][]float32, len(keep)) 112 | kpss := make([][]float32, len(keep)) 113 | for i := range keep { 114 | det[i] = bboxes_list[keep[i]] 115 | kpss[i] = kpss_list[keep[i]] 116 | } 117 | 118 | return det, kpss 119 | } 120 | 121 | 122 | func distance2bbox(points [][]float32, distance []float32) (ret [][]float32) { 123 | ret = make([][]float32, len(points)) 124 | for i := range points { 125 | ret[i] = []float32{ 126 | points[i][0] - distance[i*4+0], 127 | points[i][1] - distance[i*4+1], 128 | points[i][0] + distance[i*4+2], 129 | points[i][1] + distance[i*4+3], 130 | } 131 | } 132 | return 133 | } 134 | 135 | func distance2kps(points [][]float32, distance []float32) (ret [][]float32) { 136 | ret = make([][]float32, len(points)) 137 | for i := range points { 138 | ret[i] = make([]float32, 10) 139 | for j:=0;j<10;j=j+2 { 140 | ret[i][j] = points[i][j%2] + distance[i*10+j] 141 | ret[i][j+1] = points[i][j%2+1] + distance[i*10+j+1] 142 | } 143 | } 144 | return 145 | } 146 | 147 | 148 | func max(a, b float32) float32 { 149 | if a>b { 150 | return a 151 | } else { 152 | return b 153 | } 154 | } 155 | 156 | func min(a, b float32) float32 { 157 | if a0 { 176 | i := order[0] 177 | ret = append(ret, i) 178 | 179 | var keep []int 180 | for j := range order[1:] { 181 | xx1 := max(dets[i][0], dets[order[j+1]][0]) 182 | yy1 := max(dets[i][1], dets[order[j+1]][1]) 183 | xx2 := min(dets[i][2], dets[order[j+1]][2]) 184 | yy2 := min(dets[i][3], dets[order[j+1]][3]) 185 | 186 | w := max(0.0, xx2 - xx1 + 1) 187 | h := max(0.0, yy2 - yy1 + 1) 188 | inter := w * h 189 | ovr := inter / (areas[i] + areas[order[j+1]] - inter) 190 | 191 | if ovr <= nms_thresh { 192 | keep = append(keep, order[j+1]) 193 | } 194 | } 195 | 196 | order = keep 197 | } 198 | return 199 | } 200 | -------------------------------------------------------------------------------- /gocvx/core.h: -------------------------------------------------------------------------------- 1 | #ifndef _OPENCV3_CORE_H_ 2 | #define _OPENCV3_CORE_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Wrapper for std::vector 8 | typedef struct CStrings { 9 | const char** strs; 10 | int length; 11 | } CStrings; 12 | 13 | typedef struct ByteArray { 14 | char* data; 15 | int length; 16 | } ByteArray; 17 | 18 | // Wrapper for std::vector 19 | typedef struct IntVector { 20 | int* val; 21 | int length; 22 | } IntVector; 23 | 24 | // Wrapper for std::vector 25 | typedef struct FloatVector { 26 | float* val; 27 | int length; 28 | } FloatVector; 29 | 30 | #ifdef __cplusplus 31 | #include 32 | extern "C" { 33 | #endif 34 | 35 | typedef struct RawData { 36 | int width; 37 | int height; 38 | struct ByteArray data; 39 | } RawData; 40 | 41 | // Wrapper for an individual cv::Point2f 42 | typedef struct Point2f { 43 | float x; 44 | float y; 45 | } Point2f; 46 | 47 | typedef struct Point3f { 48 | float x; 49 | float y; 50 | float z; 51 | } Point3f; 52 | 53 | // Wrapper for an individual cv::cvPoint 54 | typedef struct Point { 55 | int x; 56 | int y; 57 | } Point; 58 | 59 | // Wrapper for the vector of Point structs aka std::vector 60 | typedef struct Points { 61 | Point* points; 62 | int length; 63 | } Points; 64 | 65 | // Wrapper for the vector of Point2f structs aka std::vector 66 | typedef struct Points2f { 67 | Point2f* points; 68 | int length; 69 | } Points2f; 70 | 71 | typedef struct Points3f { 72 | Point3f *points; 73 | int length; 74 | } Points3f; 75 | 76 | // Contour is alias for Points 77 | typedef Points Contour; 78 | 79 | 80 | // Contour2f is alias for Points2f 81 | typedef Points2f Contour2f; 82 | 83 | typedef struct Contours2f { 84 | Contour2f *contours; 85 | int length; 86 | } Contours2f; 87 | 88 | // Contour3f is alias for Points3f 89 | typedef Points3f Contour3f; 90 | 91 | // Wrapper for the vector of Points3f vectors aka std::vector< std::vector > 92 | typedef struct Contours3f { 93 | Contour3f *contours; 94 | int length; 95 | } Contours3f; 96 | 97 | 98 | // Wrapper for the vector of Points vectors aka std::vector< std::vector > 99 | typedef struct Contours { 100 | Contour* contours; 101 | int length; 102 | } Contours; 103 | 104 | // Wrapper for an individual cv::cvRect 105 | typedef struct Rect { 106 | int x; 107 | int y; 108 | int width; 109 | int height; 110 | } Rect; 111 | 112 | // Wrapper for the vector of Rect struct aka std::vector 113 | typedef struct Rects { 114 | Rect* rects; 115 | int length; 116 | } Rects; 117 | 118 | // Wrapper for an individual cv::cvSize 119 | typedef struct Size { 120 | int width; 121 | int height; 122 | } Size; 123 | 124 | // Wrapper for an individual cv::RotatedRect 125 | typedef struct RotatedRect { 126 | Points pts; 127 | Rect boundingRect; 128 | Point center; 129 | Size size; 130 | double angle; 131 | } RotatedRect; 132 | 133 | // Wrapper for an individual cv::cvScalar 134 | typedef struct Scalar { 135 | double val1; 136 | double val2; 137 | double val3; 138 | double val4; 139 | } Scalar; 140 | 141 | // Wrapper for a individual cv::KeyPoint 142 | typedef struct KeyPoint { 143 | double x; 144 | double y; 145 | double size; 146 | double angle; 147 | double response; 148 | int octave; 149 | int classID; 150 | } KeyPoint; 151 | 152 | // Wrapper for the vector of KeyPoint struct aka std::vector 153 | typedef struct KeyPoints { 154 | KeyPoint* keypoints; 155 | int length; 156 | } KeyPoints; 157 | 158 | // Wrapper for SimpleBlobDetectorParams aka SimpleBlobDetector::Params 159 | typedef struct SimpleBlobDetectorParams { 160 | unsigned char blobColor; 161 | bool filterByArea; 162 | bool filterByCircularity; 163 | bool filterByColor; 164 | bool filterByConvexity; 165 | bool filterByInertia; 166 | float maxArea; 167 | float maxCircularity; 168 | float maxConvexity; 169 | float maxInertiaRatio; 170 | float maxThreshold; 171 | float minArea; 172 | float minCircularity; 173 | float minConvexity; 174 | float minDistBetweenBlobs; 175 | float minInertiaRatio; 176 | size_t minRepeatability; 177 | float minThreshold; 178 | float thresholdStep; 179 | } SimpleBlobDetectorParams; 180 | 181 | // Wrapper for an individual cv::DMatch 182 | typedef struct DMatch { 183 | int queryIdx; 184 | int trainIdx; 185 | int imgIdx; 186 | float distance; 187 | } DMatch; 188 | 189 | // Wrapper for the vector of DMatch struct aka std::vector 190 | typedef struct DMatches { 191 | DMatch* dmatches; 192 | int length; 193 | } DMatches; 194 | 195 | // Wrapper for the vector vector of DMatch struct aka std::vector> 196 | typedef struct MultiDMatches { 197 | DMatches* dmatches; 198 | int length; 199 | } MultiDMatches; 200 | 201 | // Wrapper for an individual cv::Moment 202 | typedef struct Moment { 203 | double m00; 204 | double m10; 205 | double m01; 206 | double m20; 207 | double m11; 208 | double m02; 209 | double m30; 210 | double m21; 211 | double m12; 212 | double m03; 213 | 214 | double mu20; 215 | double mu11; 216 | double mu02; 217 | double mu30; 218 | double mu21; 219 | double mu12; 220 | double mu03; 221 | 222 | double nu20; 223 | double nu11; 224 | double nu02; 225 | double nu30; 226 | double nu21; 227 | double nu12; 228 | double nu03; 229 | } Moment; 230 | 231 | #ifdef __cplusplus 232 | typedef cv::Mat* Mat; 233 | typedef cv::TermCriteria* TermCriteria; 234 | typedef cv::RNG* RNG; 235 | typedef std::vector< cv::Point >* PointVector; 236 | typedef std::vector< std::vector< cv::Point > >* PointsVector; 237 | typedef std::vector< cv::Point2f >* Point2fVector; 238 | typedef std::vector< std::vector< cv::Point2f> >* Points2fVector; 239 | typedef std::vector< cv::Point3f >* Point3fVector; 240 | typedef std::vector< std::vector< cv::Point3f > >* Points3fVector; 241 | #else 242 | typedef void* Mat; 243 | typedef void* TermCriteria; 244 | typedef void* RNG; 245 | typedef void* PointVector; 246 | typedef void* PointsVector; 247 | typedef void* Point2fVector; 248 | typedef void* Points2fVector; 249 | typedef void* Point3fVector; 250 | typedef void* Points3fVector; 251 | #endif 252 | 253 | // Wrapper for the vector of Mat aka std::vector 254 | typedef struct Mats { 255 | Mat* mats; 256 | int length; 257 | } Mats; 258 | 259 | Mat Mats_get(struct Mats mats, int i); 260 | struct DMatches MultiDMatches_get(struct MultiDMatches mds, int index); 261 | 262 | struct ByteArray toByteArray(const char* buf, int len); 263 | void ByteArray_Release(struct ByteArray buf); 264 | 265 | void Contours_Close(struct Contours cs); 266 | void KeyPoints_Close(struct KeyPoints ks); 267 | void Rects_Close(struct Rects rs); 268 | void Mats_Close(struct Mats mats); 269 | void Point_Close(struct Point p); 270 | void Points_Close(struct Points ps); 271 | void DMatches_Close(struct DMatches ds); 272 | void MultiDMatches_Close(struct MultiDMatches mds); 273 | 274 | Mat Mat_New(); 275 | Mat Mat_NewWithSize(int rows, int cols, int type); 276 | Mat Mat_NewWithSizes(struct IntVector sizes, int type); 277 | Mat Mat_NewWithSizesFromScalar(IntVector sizes, int type, Scalar ar); 278 | Mat Mat_NewWithSizesFromBytes(IntVector sizes, int type, struct ByteArray buf); 279 | Mat Mat_NewFromScalar(const Scalar ar, int type); 280 | Mat Mat_NewWithSizeFromScalar(const Scalar ar, int rows, int cols, int type); 281 | Mat Mat_NewFromBytes(int rows, int cols, int type, struct ByteArray buf); 282 | Mat Mat_FromPtr(Mat m, int rows, int cols, int type, int prows, int pcols); 283 | void Mat_Close(Mat m); 284 | int Mat_Empty(Mat m); 285 | bool Mat_IsContinuous(Mat m); 286 | Mat Mat_Clone(Mat m); 287 | void Mat_CopyTo(Mat m, Mat dst); 288 | int Mat_Total(Mat m); 289 | void Mat_Size(Mat m, IntVector* res); 290 | void Mat_CopyToWithMask(Mat m, Mat dst, Mat mask); 291 | void Mat_ConvertTo(Mat m, Mat dst, int type); 292 | void Mat_ConvertToWithParams(Mat m, Mat dst, int type, float alpha, float beta); 293 | struct ByteArray Mat_ToBytes(Mat m); 294 | struct ByteArray Mat_DataPtr(Mat m); 295 | Mat Mat_Region(Mat m, Rect r); 296 | Mat Mat_Reshape(Mat m, int cn, int rows); 297 | void Mat_PatchNaNs(Mat m); 298 | Mat Mat_ConvertFp16(Mat m); 299 | Scalar Mat_Mean(Mat m); 300 | Scalar Mat_MeanWithMask(Mat m, Mat mask); 301 | Mat Mat_Sqrt(Mat m); 302 | int Mat_Rows(Mat m); 303 | int Mat_Cols(Mat m); 304 | int Mat_Channels(Mat m); 305 | int Mat_Type(Mat m); 306 | int Mat_Step(Mat m); 307 | Mat Eye(int rows, int cols, int type); 308 | Mat Zeros(int rows, int cols, int type); 309 | Mat Ones(int rows, int cols, int type); 310 | 311 | uint8_t Mat_GetUChar(Mat m, int row, int col); 312 | uint8_t Mat_GetUChar3(Mat m, int x, int y, int z); 313 | int8_t Mat_GetSChar(Mat m, int row, int col); 314 | int8_t Mat_GetSChar3(Mat m, int x, int y, int z); 315 | int16_t Mat_GetShort(Mat m, int row, int col); 316 | int16_t Mat_GetShort3(Mat m, int x, int y, int z); 317 | int32_t Mat_GetInt(Mat m, int row, int col); 318 | int32_t Mat_GetInt3(Mat m, int x, int y, int z); 319 | float Mat_GetFloat(Mat m, int row, int col); 320 | float Mat_GetFloat3(Mat m, int x, int y, int z); 321 | double Mat_GetDouble(Mat m, int row, int col); 322 | double Mat_GetDouble3(Mat m, int x, int y, int z); 323 | 324 | void Mat_SetTo(Mat m, Scalar value); 325 | void Mat_SetUChar(Mat m, int row, int col, uint8_t val); 326 | void Mat_SetUChar3(Mat m, int x, int y, int z, uint8_t val); 327 | void Mat_SetSChar(Mat m, int row, int col, int8_t val); 328 | void Mat_SetSChar3(Mat m, int x, int y, int z, int8_t val); 329 | void Mat_SetShort(Mat m, int row, int col, int16_t val); 330 | void Mat_SetShort3(Mat m, int x, int y, int z, int16_t val); 331 | void Mat_SetInt(Mat m, int row, int col, int32_t val); 332 | void Mat_SetInt3(Mat m, int x, int y, int z, int32_t val); 333 | void Mat_SetFloat(Mat m, int row, int col, float val); 334 | void Mat_SetFloat3(Mat m, int x, int y, int z, float val); 335 | void Mat_SetDouble(Mat m, int row, int col, double val); 336 | void Mat_SetDouble3(Mat m, int x, int y, int z, double val); 337 | 338 | void Mat_AddUChar(Mat m, uint8_t val); 339 | void Mat_SubtractUChar(Mat m, uint8_t val); 340 | void Mat_MultiplyUChar(Mat m, uint8_t val); 341 | void Mat_DivideUChar(Mat m, uint8_t val); 342 | void Mat_AddFloat(Mat m, float val); 343 | void Mat_SubtractFloat(Mat m, float val); 344 | void Mat_MultiplyFloat(Mat m, float val); 345 | void Mat_DivideFloat(Mat m, float val); 346 | Mat Mat_MultiplyMatrix(Mat x, Mat y); 347 | 348 | Mat Mat_T(Mat x); 349 | 350 | void LUT(Mat src, Mat lut, Mat dst); 351 | 352 | void Mat_AbsDiff(Mat src1, Mat src2, Mat dst); 353 | void Mat_Add(Mat src1, Mat src2, Mat dst); 354 | void Mat_AddWeighted(Mat src1, double alpha, Mat src2, double beta, double gamma, Mat dst); 355 | void Mat_BitwiseAnd(Mat src1, Mat src2, Mat dst); 356 | void Mat_BitwiseAndWithMask(Mat src1, Mat src2, Mat dst, Mat mask); 357 | void Mat_BitwiseNot(Mat src1, Mat dst); 358 | void Mat_BitwiseNotWithMask(Mat src1, Mat dst, Mat mask); 359 | void Mat_BitwiseOr(Mat src1, Mat src2, Mat dst); 360 | void Mat_BitwiseOrWithMask(Mat src1, Mat src2, Mat dst, Mat mask); 361 | void Mat_BitwiseXor(Mat src1, Mat src2, Mat dst); 362 | void Mat_BitwiseXorWithMask(Mat src1, Mat src2, Mat dst, Mat mask); 363 | void Mat_Compare(Mat src1, Mat src2, Mat dst, int ct); 364 | void Mat_BatchDistance(Mat src1, Mat src2, Mat dist, int dtype, Mat nidx, int normType, int K, 365 | Mat mask, int update, bool crosscheck); 366 | int Mat_BorderInterpolate(int p, int len, int borderType); 367 | void Mat_CalcCovarMatrix(Mat samples, Mat covar, Mat mean, int flags, int ctype); 368 | void Mat_CartToPolar(Mat x, Mat y, Mat magnitude, Mat angle, bool angleInDegrees); 369 | bool Mat_CheckRange(Mat m); 370 | void Mat_CompleteSymm(Mat m, bool lowerToUpper); 371 | void Mat_ConvertScaleAbs(Mat src, Mat dst, double alpha, double beta); 372 | void Mat_CopyMakeBorder(Mat src, Mat dst, int top, int bottom, int left, int right, int borderType, 373 | Scalar value); 374 | int Mat_CountNonZero(Mat src); 375 | void Mat_DCT(Mat src, Mat dst, int flags); 376 | double Mat_Determinant(Mat m); 377 | void Mat_DFT(Mat m, Mat dst, int flags); 378 | void Mat_Divide(Mat src1, Mat src2, Mat dst); 379 | bool Mat_Eigen(Mat src, Mat eigenvalues, Mat eigenvectors); 380 | void Mat_EigenNonSymmetric(Mat src, Mat eigenvalues, Mat eigenvectors); 381 | void Mat_Exp(Mat src, Mat dst); 382 | void Mat_ExtractChannel(Mat src, Mat dst, int coi); 383 | void Mat_FindNonZero(Mat src, Mat idx); 384 | void Mat_Flip(Mat src, Mat dst, int flipCode); 385 | void Mat_Gemm(Mat src1, Mat src2, double alpha, Mat src3, double beta, Mat dst, int flags); 386 | int Mat_GetOptimalDFTSize(int vecsize); 387 | void Mat_Hconcat(Mat src1, Mat src2, Mat dst); 388 | void Mat_Vconcat(Mat src1, Mat src2, Mat dst); 389 | void Rotate(Mat src, Mat dst, int rotationCode); 390 | void Mat_Idct(Mat src, Mat dst, int flags); 391 | void Mat_Idft(Mat src, Mat dst, int flags, int nonzeroRows); 392 | void Mat_InRange(Mat src, Mat lowerb, Mat upperb, Mat dst); 393 | void Mat_InRangeWithScalar(Mat src, const Scalar lowerb, const Scalar upperb, Mat dst); 394 | void Mat_InsertChannel(Mat src, Mat dst, int coi); 395 | double Mat_Invert(Mat src, Mat dst, int flags); 396 | double KMeans(Mat data, int k, Mat bestLabels, TermCriteria criteria, int attempts, int flags, Mat centers); 397 | double KMeansPoints(PointVector pts, int k, Mat bestLabels, TermCriteria criteria, int attempts, int flags, Mat centers); 398 | void Mat_Log(Mat src, Mat dst); 399 | void Mat_Magnitude(Mat x, Mat y, Mat magnitude); 400 | void Mat_Max(Mat src1, Mat src2, Mat dst); 401 | void Mat_MeanStdDev(Mat src, Mat dstMean, Mat dstStdDev); 402 | void Mat_Merge(struct Mats mats, Mat dst); 403 | void Mat_Min(Mat src1, Mat src2, Mat dst); 404 | void Mat_MinMaxIdx(Mat m, double* minVal, double* maxVal, int* minIdx, int* maxIdx); 405 | void Mat_MinMaxLoc(Mat m, double* minVal, double* maxVal, Point* minLoc, Point* maxLoc); 406 | void Mat_MixChannels(struct Mats src, struct Mats dst, struct IntVector fromTo); 407 | void Mat_MulSpectrums(Mat a, Mat b, Mat c, int flags); 408 | void Mat_Multiply(Mat src1, Mat src2, Mat dst); 409 | void Mat_MultiplyWithParams(Mat src1, Mat src2, Mat dst, double scale, int dtype); 410 | void Mat_Subtract(Mat src1, Mat src2, Mat dst); 411 | void Mat_Normalize(Mat src, Mat dst, double alpha, double beta, int typ); 412 | double Norm(Mat src1, int normType); 413 | double NormWithMats(Mat src1, Mat src2, int normType); 414 | void Mat_PerspectiveTransform(Mat src, Mat dst, Mat tm); 415 | bool Mat_Solve(Mat src1, Mat src2, Mat dst, int flags); 416 | int Mat_SolveCubic(Mat coeffs, Mat roots); 417 | double Mat_SolvePoly(Mat coeffs, Mat roots, int maxIters); 418 | void Mat_Reduce(Mat src, Mat dst, int dim, int rType, int dType); 419 | void Mat_Repeat(Mat src, int nY, int nX, Mat dst); 420 | void Mat_ScaleAdd(Mat src1, double alpha, Mat src2, Mat dst); 421 | void Mat_SetIdentity(Mat src, double scalar); 422 | void Mat_Sort(Mat src, Mat dst, int flags); 423 | void Mat_SortIdx(Mat src, Mat dst, int flags); 424 | void Mat_Split(Mat src, struct Mats* mats); 425 | void Mat_Subtract(Mat src1, Mat src2, Mat dst); 426 | Scalar Mat_Trace(Mat src); 427 | void Mat_Transform(Mat src, Mat dst, Mat tm); 428 | void Mat_Transpose(Mat src, Mat dst); 429 | void Mat_PolarToCart(Mat magnitude, Mat degree, Mat x, Mat y, bool angleInDegrees); 430 | void Mat_Pow(Mat src, double power, Mat dst); 431 | void Mat_Phase(Mat x, Mat y, Mat angle, bool angleInDegrees); 432 | Scalar Mat_Sum(Mat src1); 433 | 434 | TermCriteria TermCriteria_New(int typ, int maxCount, double epsilon); 435 | 436 | int64_t GetCVTickCount(); 437 | double GetTickFrequency(); 438 | 439 | Mat Mat_rowRange(Mat m,int startrow,int endrow); 440 | Mat Mat_colRange(Mat m,int startrow,int endrow); 441 | 442 | PointVector PointVector_New(); 443 | PointVector PointVector_NewFromPoints(Contour points); 444 | PointVector PointVector_NewFromMat(Mat mat); 445 | Point PointVector_At(PointVector pv, int idx); 446 | void PointVector_Append(PointVector pv, Point p); 447 | int PointVector_Size(PointVector pv); 448 | void PointVector_Close(PointVector pv); 449 | 450 | PointsVector PointsVector_New(); 451 | PointsVector PointsVector_NewFromPoints(Contours points); 452 | PointVector PointsVector_At(PointsVector psv, int idx); 453 | void PointsVector_Append(PointsVector psv, PointVector pv); 454 | int PointsVector_Size(PointsVector psv); 455 | void PointsVector_Close(PointsVector psv); 456 | 457 | Point2fVector Point2fVector_New(); 458 | void Point2fVector_Close(Point2fVector pfv); 459 | Point2fVector Point2fVector_NewFromPoints(Contour2f pts); 460 | Point2fVector Point2fVector_NewFromMat(Mat mat); 461 | Point2f Point2fVector_At(Point2fVector pfv, int idx); 462 | int Point2fVector_Size(Point2fVector pfv); 463 | 464 | void IntVector_Close(struct IntVector ivec); 465 | 466 | void CStrings_Close(struct CStrings cstrs); 467 | 468 | RNG TheRNG(); 469 | 470 | void SetRNGSeed(int seed); 471 | 472 | void RNG_Fill(RNG rng, Mat mat, int distType, double a, double b, bool saturateRange); 473 | 474 | double RNG_Gaussian(RNG rng, double sigma); 475 | 476 | unsigned int RNG_Next(RNG rng); 477 | 478 | void RandN(Mat mat, Scalar mean, Scalar stddev); 479 | 480 | void RandShuffle(Mat mat); 481 | 482 | void RandShuffleWithParams(Mat mat, double iterFactor, RNG rng); 483 | 484 | void RandU(Mat mat, Scalar low, Scalar high); 485 | 486 | void copyPointVectorToPoint2fVector(PointVector src, Point2fVector dest); 487 | 488 | void StdByteVectorInitialize(void* data); 489 | void StdByteVectorFree(void *data); 490 | size_t StdByteVectorLen(void *data); 491 | uint8_t* StdByteVectorData(void *data); 492 | 493 | Points2fVector Points2fVector_New(); 494 | Points2fVector Points2fVector_NewFromPoints(Contours2f points); 495 | int Points2fVector_Size(Points2fVector ps); 496 | Point2fVector Points2fVector_At(Points2fVector ps, int idx); 497 | void Points2fVector_Append(Points2fVector psv, Point2fVector pv); 498 | void Points2fVector_Close(Points2fVector ps); 499 | 500 | Point3fVector Point3fVector_New(); 501 | Point3fVector Point3fVector_NewFromPoints(Contour3f points); 502 | Point3fVector Point3fVector_NewFromMat(Mat mat); 503 | void Point3fVector_Append(Point3fVector pfv, Point3f point); 504 | Point3f Point3fVector_At(Point3fVector pfv, int idx); 505 | int Point3fVector_Size(Point3fVector pfv); 506 | void Point3fVector_Close(Point3fVector pv); 507 | Points3fVector Points3fVector_New(); 508 | Points3fVector Points3fVector_NewFromPoints(Contours3f points); 509 | int Points3fVector_Size(Points3fVector ps); 510 | Point3fVector Points3fVector_At(Points3fVector ps, int idx); 511 | void Points3fVector_Append(Points3fVector psv, Point3fVector pv); 512 | void Points3fVector_Close(Points3fVector ps); 513 | 514 | #ifdef __cplusplus 515 | } 516 | #endif 517 | 518 | #endif //_OPENCV3_CORE_H_ 519 | -------------------------------------------------------------------------------- /gocvx/core.cpp: -------------------------------------------------------------------------------- 1 | #include "core.h" 2 | #include 3 | 4 | // Mat_New creates a new empty Mat 5 | Mat Mat_New() { 6 | return new cv::Mat(); 7 | } 8 | 9 | // Mat_NewWithSize creates a new Mat with a specific size dimension and number of channels. 10 | Mat Mat_NewWithSize(int rows, int cols, int type) { 11 | return new cv::Mat(rows, cols, type, 0.0); 12 | } 13 | 14 | // Mat_NewWithSizes creates a new Mat with specific dimension sizes and number of channels. 15 | Mat Mat_NewWithSizes(struct IntVector sizes, int type) { 16 | std::vector sizess; 17 | for (int i = 0; i < sizes.length; ++i) { 18 | sizess.push_back(sizes.val[i]); 19 | } 20 | return new cv::Mat(sizess, type); 21 | } 22 | 23 | // Mat_NewFromScalar creates a new Mat from a Scalar. Intended to be used 24 | // for Mat comparison operation such as InRange. 25 | Mat Mat_NewFromScalar(Scalar ar, int type) { 26 | cv::Scalar c = cv::Scalar(ar.val1, ar.val2, ar.val3, ar.val4); 27 | return new cv::Mat(1, 1, type, c); 28 | } 29 | 30 | // Mat_NewWithSizeFromScalar creates a new Mat from a Scalar with a specific size dimension and number of channels 31 | Mat Mat_NewWithSizeFromScalar(Scalar ar, int rows, int cols, int type) { 32 | cv::Scalar c = cv::Scalar(ar.val1, ar.val2, ar.val3, ar.val4); 33 | return new cv::Mat(rows, cols, type, c); 34 | } 35 | 36 | Mat Mat_NewFromBytes(int rows, int cols, int type, struct ByteArray buf) { 37 | return new cv::Mat(rows, cols, type, buf.data); 38 | } 39 | 40 | // Mat_NewWithSizesFromScalar creates multidimensional Mat from a scalar 41 | Mat Mat_NewWithSizesFromScalar(IntVector sizes, int type, Scalar ar) { 42 | std::vector _sizes; 43 | for (int i = 0, *v = sizes.val; i < sizes.length; ++v, ++i) { 44 | _sizes.push_back(*v); 45 | } 46 | 47 | cv::Scalar c = cv::Scalar(ar.val1, ar.val2, ar.val3, ar.val4); 48 | return new cv::Mat(_sizes, type, c); 49 | } 50 | 51 | // Mat_NewWithSizesFromBytes creates multidimensional Mat from a bytes 52 | Mat Mat_NewWithSizesFromBytes(IntVector sizes, int type, struct ByteArray buf) { 53 | std::vector _sizes; 54 | for (int i = 0, *v = sizes.val; i < sizes.length; ++v, ++i) { 55 | _sizes.push_back(*v); 56 | } 57 | 58 | return new cv::Mat(_sizes, type, buf.data); 59 | } 60 | 61 | Mat Eye(int rows, int cols, int type) { 62 | cv::Mat* mat = new cv::Mat(rows, cols, type); 63 | *mat = cv::Mat::eye(rows, cols, type); 64 | return mat; 65 | } 66 | 67 | Mat Zeros(int rows, int cols, int type) { 68 | cv::Mat* mat = new cv::Mat(rows, cols, type); 69 | *mat = cv::Mat::zeros(rows, cols, type); 70 | return mat; 71 | } 72 | 73 | Mat Ones(int rows, int cols, int type) { 74 | cv::Mat* mat = new cv::Mat(rows, cols, type); 75 | *mat = cv::Mat::ones(rows, cols, type); 76 | return mat; 77 | } 78 | 79 | Mat Mat_FromPtr(Mat m, int rows, int cols, int type, int prow, int pcol) { 80 | return new cv::Mat(rows, cols, type, m->ptr(prow, pcol)); 81 | } 82 | 83 | // Mat_Close deletes an existing Mat 84 | void Mat_Close(Mat m) { 85 | delete m; 86 | } 87 | 88 | // Mat_Empty tests if a Mat is empty 89 | int Mat_Empty(Mat m) { 90 | return m->empty(); 91 | } 92 | 93 | // Mat_IsContinuous tests if a Mat is continuous 94 | bool Mat_IsContinuous(Mat m) { 95 | return m->isContinuous(); 96 | } 97 | 98 | // Mat_Clone returns a clone of this Mat 99 | Mat Mat_Clone(Mat m) { 100 | return new cv::Mat(m->clone()); 101 | } 102 | 103 | // Mat_CopyTo copies this Mat to another Mat. 104 | void Mat_CopyTo(Mat m, Mat dst) { 105 | m->copyTo(*dst); 106 | } 107 | 108 | // Mat_CopyToWithMask copies this Mat to another Mat while applying the mask 109 | void Mat_CopyToWithMask(Mat m, Mat dst, Mat mask) { 110 | m->copyTo(*dst, *mask); 111 | } 112 | 113 | void Mat_ConvertTo(Mat m, Mat dst, int type) { 114 | m->convertTo(*dst, type); 115 | } 116 | 117 | void Mat_ConvertToWithParams(Mat m, Mat dst, int type, float alpha, float beta) { 118 | m->convertTo(*dst, type, alpha, beta); 119 | } 120 | 121 | // Mat_ToBytes returns the bytes representation of the underlying data. 122 | struct ByteArray Mat_ToBytes(Mat m) { 123 | return toByteArray(reinterpret_cast(m->data), m->total() * m->elemSize()); 124 | } 125 | 126 | struct ByteArray Mat_DataPtr(Mat m) { 127 | return ByteArray {reinterpret_cast(m->data), static_cast(m->total() * m->elemSize())}; 128 | } 129 | 130 | // Mat_Region returns a Mat of a region of another Mat 131 | Mat Mat_Region(Mat m, Rect r) { 132 | return new cv::Mat(*m, cv::Rect(r.x, r.y, r.width, r.height)); 133 | } 134 | 135 | Mat Mat_Reshape(Mat m, int cn, int rows) { 136 | return new cv::Mat(m->reshape(cn, rows)); 137 | } 138 | 139 | void Mat_PatchNaNs(Mat m) { 140 | cv::patchNaNs(*m); 141 | } 142 | 143 | Mat Mat_ConvertFp16(Mat m) { 144 | Mat dst = new cv::Mat(); 145 | cv::convertFp16(*m, *dst); 146 | return dst; 147 | } 148 | 149 | Mat Mat_Sqrt(Mat m) { 150 | Mat dst = new cv::Mat(); 151 | cv::sqrt(*m, *dst); 152 | return dst; 153 | } 154 | 155 | // Mat_Mean calculates the mean value M of array elements, independently for each channel, and return it as Scalar vector 156 | Scalar Mat_Mean(Mat m) { 157 | cv::Scalar c = cv::mean(*m); 158 | Scalar scal = Scalar(); 159 | scal.val1 = c.val[0]; 160 | scal.val2 = c.val[1]; 161 | scal.val3 = c.val[2]; 162 | scal.val4 = c.val[3]; 163 | return scal; 164 | } 165 | 166 | // Mat_MeanWithMask calculates the mean value M of array elements, 167 | // independently for each channel, and returns it as Scalar vector 168 | // while applying the mask. 169 | 170 | Scalar Mat_MeanWithMask(Mat m, Mat mask){ 171 | cv::Scalar c = cv::mean(*m, *mask); 172 | Scalar scal = Scalar(); 173 | scal.val1 = c.val[0]; 174 | scal.val2 = c.val[1]; 175 | scal.val3 = c.val[2]; 176 | scal.val4 = c.val[3]; 177 | return scal; 178 | } 179 | 180 | void LUT(Mat src, Mat lut, Mat dst) { 181 | cv::LUT(*src, *lut, *dst); 182 | } 183 | 184 | // Mat_Rows returns how many rows in this Mat. 185 | int Mat_Rows(Mat m) { 186 | return m->rows; 187 | } 188 | 189 | // Mat_Cols returns how many columns in this Mat. 190 | int Mat_Cols(Mat m) { 191 | return m->cols; 192 | } 193 | 194 | // Mat_Channels returns how many channels in this Mat. 195 | int Mat_Channels(Mat m) { 196 | return m->channels(); 197 | } 198 | 199 | // Mat_Type returns the type from this Mat. 200 | int Mat_Type(Mat m) { 201 | return m->type(); 202 | } 203 | 204 | // Mat_Step returns the number of bytes each matrix row occupies. 205 | int Mat_Step(Mat m) { 206 | return m->step; 207 | } 208 | 209 | int Mat_Total(Mat m) { 210 | return m->total(); 211 | } 212 | 213 | void Mat_Size(Mat m, IntVector* res) { 214 | cv::MatSize ms(m->size); 215 | int* ids = new int[ms.dims()]; 216 | 217 | for (size_t i = 0; i < ms.dims(); ++i) { 218 | ids[i] = ms[i]; 219 | } 220 | 221 | res->length = ms.dims(); 222 | res->val = ids; 223 | return; 224 | } 225 | 226 | // Mat_GetUChar returns a specific row/col value from this Mat expecting 227 | // each element to contain a schar aka CV_8U. 228 | uint8_t Mat_GetUChar(Mat m, int row, int col) { 229 | return m->at(row, col); 230 | } 231 | 232 | uint8_t Mat_GetUChar3(Mat m, int x, int y, int z) { 233 | return m->at(x, y, z); 234 | } 235 | 236 | // Mat_GetSChar returns a specific row/col value from this Mat expecting 237 | // each element to contain a schar aka CV_8S. 238 | int8_t Mat_GetSChar(Mat m, int row, int col) { 239 | return m->at(row, col); 240 | } 241 | 242 | int8_t Mat_GetSChar3(Mat m, int x, int y, int z) { 243 | return m->at(x, y, z); 244 | } 245 | 246 | // Mat_GetShort returns a specific row/col value from this Mat expecting 247 | // each element to contain a short aka CV_16S. 248 | int16_t Mat_GetShort(Mat m, int row, int col) { 249 | return m->at(row, col); 250 | } 251 | 252 | int16_t Mat_GetShort3(Mat m, int x, int y, int z) { 253 | return m->at(x, y, z); 254 | } 255 | 256 | // Mat_GetInt returns a specific row/col value from this Mat expecting 257 | // each element to contain an int aka CV_32S. 258 | int32_t Mat_GetInt(Mat m, int row, int col) { 259 | return m->at(row, col); 260 | } 261 | 262 | int32_t Mat_GetInt3(Mat m, int x, int y, int z) { 263 | return m->at(x, y, z); 264 | } 265 | 266 | // Mat_GetFloat returns a specific row/col value from this Mat expecting 267 | // each element to contain a float aka CV_32F. 268 | float Mat_GetFloat(Mat m, int row, int col) { 269 | return m->at(row, col); 270 | } 271 | 272 | float Mat_GetFloat3(Mat m, int x, int y, int z) { 273 | return m->at(x, y, z); 274 | } 275 | 276 | // Mat_GetDouble returns a specific row/col value from this Mat expecting 277 | // each element to contain a double aka CV_64F. 278 | double Mat_GetDouble(Mat m, int row, int col) { 279 | return m->at(row, col); 280 | } 281 | 282 | double Mat_GetDouble3(Mat m, int x, int y, int z) { 283 | return m->at(x, y, z); 284 | } 285 | 286 | void Mat_SetTo(Mat m, Scalar value) { 287 | cv::Scalar c_value(value.val1, value.val2, value.val3, value.val4); 288 | m->setTo(c_value); 289 | } 290 | 291 | // Mat_SetUChar set a specific row/col value from this Mat expecting 292 | // each element to contain a schar aka CV_8U. 293 | void Mat_SetUChar(Mat m, int row, int col, uint8_t val) { 294 | m->at(row, col) = val; 295 | } 296 | 297 | void Mat_SetUChar3(Mat m, int x, int y, int z, uint8_t val) { 298 | m->at(x, y, z) = val; 299 | } 300 | 301 | // Mat_SetSChar set a specific row/col value from this Mat expecting 302 | // each element to contain a schar aka CV_8S. 303 | void Mat_SetSChar(Mat m, int row, int col, int8_t val) { 304 | m->at(row, col) = val; 305 | } 306 | 307 | void Mat_SetSChar3(Mat m, int x, int y, int z, int8_t val) { 308 | m->at(x, y, z) = val; 309 | } 310 | 311 | // Mat_SetShort set a specific row/col value from this Mat expecting 312 | // each element to contain a short aka CV_16S. 313 | void Mat_SetShort(Mat m, int row, int col, int16_t val) { 314 | m->at(row, col) = val; 315 | } 316 | 317 | void Mat_SetShort3(Mat m, int x, int y, int z, int16_t val) { 318 | m->at(x, y, z) = val; 319 | } 320 | 321 | // Mat_SetInt set a specific row/col value from this Mat expecting 322 | // each element to contain an int aka CV_32S. 323 | void Mat_SetInt(Mat m, int row, int col, int32_t val) { 324 | m->at(row, col) = val; 325 | } 326 | 327 | void Mat_SetInt3(Mat m, int x, int y, int z, int32_t val) { 328 | m->at(x, y, z) = val; 329 | } 330 | 331 | // Mat_SetFloat set a specific row/col value from this Mat expecting 332 | // each element to contain a float aka CV_32F. 333 | void Mat_SetFloat(Mat m, int row, int col, float val) { 334 | m->at(row, col) = val; 335 | } 336 | 337 | void Mat_SetFloat3(Mat m, int x, int y, int z, float val) { 338 | m->at(x, y, z) = val; 339 | } 340 | 341 | // Mat_SetDouble set a specific row/col value from this Mat expecting 342 | // each element to contain a double aka CV_64F. 343 | void Mat_SetDouble(Mat m, int row, int col, double val) { 344 | m->at(row, col) = val; 345 | } 346 | 347 | void Mat_SetDouble3(Mat m, int x, int y, int z, double val) { 348 | m->at(x, y, z) = val; 349 | } 350 | 351 | void Mat_AddUChar(Mat m, uint8_t val) { 352 | *m += val; 353 | } 354 | 355 | void Mat_SubtractUChar(Mat m, uint8_t val) { 356 | *m -= val; 357 | } 358 | 359 | void Mat_MultiplyUChar(Mat m, uint8_t val) { 360 | *m *= val; 361 | } 362 | 363 | void Mat_DivideUChar(Mat m, uint8_t val) { 364 | *m /= val; 365 | } 366 | 367 | void Mat_AddFloat(Mat m, float val) { 368 | *m += val; 369 | } 370 | 371 | void Mat_SubtractFloat(Mat m, float val) { 372 | *m -= val; 373 | } 374 | 375 | void Mat_MultiplyFloat(Mat m, float val) { 376 | *m *= val; 377 | } 378 | 379 | void Mat_DivideFloat(Mat m, float val) { 380 | *m /= val; 381 | } 382 | 383 | Mat Mat_MultiplyMatrix(Mat x, Mat y) { 384 | return new cv::Mat((*x) * (*y)); 385 | } 386 | 387 | Mat Mat_T(Mat x) { 388 | return new cv::Mat(x->t()); 389 | } 390 | 391 | void Mat_AbsDiff(Mat src1, Mat src2, Mat dst) { 392 | cv::absdiff(*src1, *src2, *dst); 393 | } 394 | 395 | void Mat_Add(Mat src1, Mat src2, Mat dst) { 396 | cv::add(*src1, *src2, *dst); 397 | } 398 | 399 | void Mat_AddWeighted(Mat src1, double alpha, Mat src2, double beta, double gamma, Mat dst) { 400 | cv::addWeighted(*src1, alpha, *src2, beta, gamma, *dst); 401 | } 402 | 403 | void Mat_BitwiseAnd(Mat src1, Mat src2, Mat dst) { 404 | cv::bitwise_and(*src1, *src2, *dst); 405 | } 406 | 407 | void Mat_BitwiseAndWithMask(Mat src1, Mat src2, Mat dst, Mat mask){ 408 | cv::bitwise_and(*src1, *src2, *dst, *mask); 409 | } 410 | 411 | void Mat_BitwiseNot(Mat src1, Mat dst) { 412 | cv::bitwise_not(*src1, *dst); 413 | } 414 | 415 | void Mat_BitwiseNotWithMask(Mat src1, Mat dst, Mat mask) { 416 | cv::bitwise_not(*src1, *dst, *mask); 417 | } 418 | 419 | void Mat_BitwiseOr(Mat src1, Mat src2, Mat dst) { 420 | cv::bitwise_or(*src1, *src2, *dst); 421 | } 422 | 423 | void Mat_BitwiseOrWithMask(Mat src1, Mat src2, Mat dst, Mat mask) { 424 | cv::bitwise_or(*src1, *src2, *dst, *mask); 425 | } 426 | 427 | void Mat_BitwiseXor(Mat src1, Mat src2, Mat dst) { 428 | cv::bitwise_xor(*src1, *src2, *dst); 429 | } 430 | 431 | void Mat_BitwiseXorWithMask(Mat src1, Mat src2, Mat dst, Mat mask) { 432 | cv::bitwise_xor(*src1, *src2, *dst, *mask); 433 | } 434 | 435 | void Mat_BatchDistance(Mat src1, Mat src2, Mat dist, int dtype, Mat nidx, int normType, int K, 436 | Mat mask, int update, bool crosscheck) { 437 | cv::batchDistance(*src1, *src2, *dist, dtype, *nidx, normType, K, *mask, update, crosscheck); 438 | } 439 | 440 | int Mat_BorderInterpolate(int p, int len, int borderType) { 441 | return cv::borderInterpolate(p, len, borderType); 442 | } 443 | 444 | void Mat_CalcCovarMatrix(Mat samples, Mat covar, Mat mean, int flags, int ctype) { 445 | cv::calcCovarMatrix(*samples, *covar, *mean, flags, ctype); 446 | } 447 | 448 | void Mat_CartToPolar(Mat x, Mat y, Mat magnitude, Mat angle, bool angleInDegrees) { 449 | cv::cartToPolar(*x, *y, *magnitude, *angle, angleInDegrees); 450 | } 451 | 452 | bool Mat_CheckRange(Mat m) { 453 | return cv::checkRange(*m); 454 | } 455 | 456 | void Mat_Compare(Mat src1, Mat src2, Mat dst, int ct) { 457 | cv::compare(*src1, *src2, *dst, ct); 458 | } 459 | 460 | int Mat_CountNonZero(Mat src) { 461 | return cv::countNonZero(*src); 462 | } 463 | 464 | 465 | void Mat_CompleteSymm(Mat m, bool lowerToUpper) { 466 | cv::completeSymm(*m, lowerToUpper); 467 | } 468 | 469 | void Mat_ConvertScaleAbs(Mat src, Mat dst, double alpha, double beta) { 470 | cv::convertScaleAbs(*src, *dst, alpha, beta); 471 | } 472 | 473 | void Mat_CopyMakeBorder(Mat src, Mat dst, int top, int bottom, int left, int right, int borderType, 474 | Scalar value) { 475 | cv::Scalar c_value(value.val1, value.val2, value.val3, value.val4); 476 | cv::copyMakeBorder(*src, *dst, top, bottom, left, right, borderType, c_value); 477 | } 478 | 479 | void Mat_DCT(Mat src, Mat dst, int flags) { 480 | cv::dct(*src, *dst, flags); 481 | } 482 | 483 | double Mat_Determinant(Mat m) { 484 | return cv::determinant(*m); 485 | } 486 | 487 | void Mat_DFT(Mat m, Mat dst, int flags) { 488 | cv::dft(*m, *dst, flags); 489 | } 490 | 491 | void Mat_Divide(Mat src1, Mat src2, Mat dst) { 492 | cv::divide(*src1, *src2, *dst); 493 | } 494 | 495 | bool Mat_Eigen(Mat src, Mat eigenvalues, Mat eigenvectors) { 496 | return cv::eigen(*src, *eigenvalues, *eigenvectors); 497 | } 498 | 499 | void Mat_EigenNonSymmetric(Mat src, Mat eigenvalues, Mat eigenvectors) { 500 | cv::eigenNonSymmetric(*src, *eigenvalues, *eigenvectors); 501 | } 502 | 503 | void Mat_Exp(Mat src, Mat dst) { 504 | cv::exp(*src, *dst); 505 | } 506 | 507 | void Mat_ExtractChannel(Mat src, Mat dst, int coi) { 508 | cv::extractChannel(*src, *dst, coi); 509 | } 510 | 511 | void Mat_FindNonZero(Mat src, Mat idx) { 512 | cv::findNonZero(*src, *idx); 513 | } 514 | 515 | void Mat_Flip(Mat src, Mat dst, int flipCode) { 516 | cv::flip(*src, *dst, flipCode); 517 | } 518 | 519 | void Mat_Gemm(Mat src1, Mat src2, double alpha, Mat src3, double beta, Mat dst, int flags) { 520 | cv::gemm(*src1, *src2, alpha, *src3, beta, *dst, flags); 521 | } 522 | 523 | int Mat_GetOptimalDFTSize(int vecsize) { 524 | return cv::getOptimalDFTSize(vecsize); 525 | } 526 | 527 | void Mat_Hconcat(Mat src1, Mat src2, Mat dst) { 528 | cv::hconcat(*src1, *src2, *dst); 529 | } 530 | 531 | void Mat_Vconcat(Mat src1, Mat src2, Mat dst) { 532 | cv::vconcat(*src1, *src2, *dst); 533 | } 534 | 535 | void Rotate(Mat src, Mat dst, int rotateCode) { 536 | cv::rotate(*src, *dst, rotateCode); 537 | } 538 | 539 | void Mat_Idct(Mat src, Mat dst, int flags) { 540 | cv::idct(*src, *dst, flags); 541 | } 542 | 543 | void Mat_Idft(Mat src, Mat dst, int flags, int nonzeroRows) { 544 | cv::idft(*src, *dst, flags, nonzeroRows); 545 | } 546 | 547 | void Mat_InRange(Mat src, Mat lowerb, Mat upperb, Mat dst) { 548 | cv::inRange(*src, *lowerb, *upperb, *dst); 549 | } 550 | 551 | void Mat_InRangeWithScalar(Mat src, Scalar lowerb, Scalar upperb, Mat dst) { 552 | cv::Scalar lb = cv::Scalar(lowerb.val1, lowerb.val2, lowerb.val3, lowerb.val4); 553 | cv::Scalar ub = cv::Scalar(upperb.val1, upperb.val2, upperb.val3, upperb.val4); 554 | cv::inRange(*src, lb, ub, *dst); 555 | } 556 | 557 | void Mat_InsertChannel(Mat src, Mat dst, int coi) { 558 | cv::insertChannel(*src, *dst, coi); 559 | } 560 | 561 | double Mat_Invert(Mat src, Mat dst, int flags) { 562 | double ret = cv::invert(*src, *dst, flags); 563 | return ret; 564 | } 565 | 566 | double KMeans(Mat data, int k, Mat bestLabels, TermCriteria criteria, int attempts, int flags, Mat centers) { 567 | double ret = cv::kmeans(*data, k, *bestLabels, *criteria, attempts, flags, *centers); 568 | return ret; 569 | } 570 | 571 | double KMeansPoints(PointVector points, int k, Mat bestLabels, TermCriteria criteria, int attempts, int flags, Mat centers) { 572 | std::vector pts; 573 | copyPointVectorToPoint2fVector(points, &pts); 574 | double ret = cv::kmeans(pts, k, *bestLabels, *criteria, attempts, flags, *centers); 575 | return ret; 576 | } 577 | 578 | void Mat_Log(Mat src, Mat dst) { 579 | cv::log(*src, *dst); 580 | } 581 | 582 | void Mat_Magnitude(Mat x, Mat y, Mat magnitude) { 583 | cv::magnitude(*x, *y, *magnitude); 584 | } 585 | 586 | void Mat_Max(Mat src1, Mat src2, Mat dst) { 587 | cv::max(*src1, *src2, *dst); 588 | } 589 | 590 | void Mat_MeanStdDev(Mat src, Mat dstMean, Mat dstStdDev) { 591 | cv::meanStdDev(*src, *dstMean, *dstStdDev); 592 | } 593 | 594 | void Mat_Merge(struct Mats mats, Mat dst) { 595 | std::vector images; 596 | 597 | for (int i = 0; i < mats.length; ++i) { 598 | images.push_back(*mats.mats[i]); 599 | } 600 | 601 | cv::merge(images, *dst); 602 | } 603 | 604 | void Mat_Min(Mat src1, Mat src2, Mat dst) { 605 | cv::min(*src1, *src2, *dst); 606 | } 607 | 608 | void Mat_MinMaxIdx(Mat m, double* minVal, double* maxVal, int* minIdx, int* maxIdx) { 609 | cv::minMaxIdx(*m, minVal, maxVal, minIdx, maxIdx); 610 | } 611 | 612 | void Mat_MinMaxLoc(Mat m, double* minVal, double* maxVal, Point* minLoc, Point* maxLoc) { 613 | cv::Point cMinLoc; 614 | cv::Point cMaxLoc; 615 | cv::minMaxLoc(*m, minVal, maxVal, &cMinLoc, &cMaxLoc); 616 | 617 | minLoc->x = cMinLoc.x; 618 | minLoc->y = cMinLoc.y; 619 | maxLoc->x = cMaxLoc.x; 620 | maxLoc->y = cMaxLoc.y; 621 | } 622 | 623 | void Mat_MixChannels(struct Mats src, struct Mats dst, struct IntVector fromTo) { 624 | std::vector srcMats; 625 | 626 | for (int i = 0; i < src.length; ++i) { 627 | srcMats.push_back(*src.mats[i]); 628 | } 629 | 630 | std::vector dstMats; 631 | 632 | for (int i = 0; i < dst.length; ++i) { 633 | dstMats.push_back(*dst.mats[i]); 634 | } 635 | 636 | std::vector fromTos; 637 | 638 | for (int i = 0; i < fromTo.length; ++i) { 639 | fromTos.push_back(fromTo.val[i]); 640 | } 641 | 642 | cv::mixChannels(srcMats, dstMats, fromTos); 643 | } 644 | 645 | void Mat_MulSpectrums(Mat a, Mat b, Mat c, int flags) { 646 | cv::mulSpectrums(*a, *b, *c, flags); 647 | } 648 | 649 | void Mat_Multiply(Mat src1, Mat src2, Mat dst) { 650 | cv::multiply(*src1, *src2, *dst); 651 | } 652 | 653 | void Mat_MultiplyWithParams(Mat src1, Mat src2, Mat dst, double scale, int dtype) { 654 | cv::multiply(*src1, *src2, *dst, scale, dtype); 655 | } 656 | 657 | void Mat_Normalize(Mat src, Mat dst, double alpha, double beta, int typ) { 658 | cv::normalize(*src, *dst, alpha, beta, typ); 659 | } 660 | 661 | double Norm(Mat src1, int normType) { 662 | return cv::norm(*src1, normType); 663 | } 664 | 665 | double NormWithMats(Mat src1, Mat src2, int normType) { 666 | return cv::norm(*src1, *src2, normType); 667 | } 668 | 669 | void Mat_PerspectiveTransform(Mat src, Mat dst, Mat tm) { 670 | cv::perspectiveTransform(*src, *dst, *tm); 671 | } 672 | 673 | bool Mat_Solve(Mat src1, Mat src2, Mat dst, int flags) { 674 | return cv::solve(*src1, *src2, *dst, flags); 675 | } 676 | 677 | int Mat_SolveCubic(Mat coeffs, Mat roots) { 678 | return cv::solveCubic(*coeffs, *roots); 679 | } 680 | 681 | double Mat_SolvePoly(Mat coeffs, Mat roots, int maxIters) { 682 | return cv::solvePoly(*coeffs, *roots, maxIters); 683 | } 684 | 685 | void Mat_Reduce(Mat src, Mat dst, int dim, int rType, int dType) { 686 | cv::reduce(*src, *dst, dim, rType, dType); 687 | } 688 | 689 | void Mat_Repeat(Mat src, int nY, int nX, Mat dst) { 690 | cv::repeat(*src, nY, nX, *dst); 691 | } 692 | 693 | void Mat_ScaleAdd(Mat src1, double alpha, Mat src2, Mat dst) { 694 | cv::scaleAdd(*src1, alpha, *src2, *dst); 695 | } 696 | 697 | void Mat_SetIdentity(Mat src, double scalar) { 698 | cv::setIdentity(*src, scalar); 699 | } 700 | 701 | void Mat_Sort(Mat src, Mat dst, int flags) { 702 | cv::sort(*src, *dst, flags); 703 | } 704 | 705 | void Mat_SortIdx(Mat src, Mat dst, int flags) { 706 | cv::sortIdx(*src, *dst, flags); 707 | } 708 | 709 | void Mat_Split(Mat src, struct Mats* mats) { 710 | std::vector channels; 711 | cv::split(*src, channels); 712 | mats->mats = new Mat[channels.size()]; 713 | 714 | for (size_t i = 0; i < channels.size(); ++i) { 715 | mats->mats[i] = new cv::Mat(channels[i]); 716 | } 717 | 718 | mats->length = (int)channels.size(); 719 | } 720 | 721 | void Mat_Subtract(Mat src1, Mat src2, Mat dst) { 722 | cv::subtract(*src1, *src2, *dst); 723 | } 724 | 725 | Scalar Mat_Trace(Mat src) { 726 | cv::Scalar c = cv::trace(*src); 727 | Scalar scal = Scalar(); 728 | scal.val1 = c.val[0]; 729 | scal.val2 = c.val[1]; 730 | scal.val3 = c.val[2]; 731 | scal.val4 = c.val[3]; 732 | return scal; 733 | } 734 | 735 | void Mat_Transform(Mat src, Mat dst, Mat tm) { 736 | cv::transform(*src, *dst, *tm); 737 | } 738 | 739 | void Mat_Transpose(Mat src, Mat dst) { 740 | cv::transpose(*src, *dst); 741 | } 742 | 743 | void Mat_PolarToCart(Mat magnitude, Mat degree, Mat x, Mat y, bool angleInDegrees) { 744 | cv::polarToCart(*magnitude, *degree, *x, *y, angleInDegrees); 745 | } 746 | 747 | void Mat_Pow(Mat src, double power, Mat dst) { 748 | cv::pow(*src, power, *dst); 749 | } 750 | 751 | void Mat_Phase(Mat x, Mat y, Mat angle, bool angleInDegrees) { 752 | cv::phase(*x, *y, *angle, angleInDegrees); 753 | } 754 | 755 | 756 | Scalar Mat_Sum(Mat src) { 757 | cv::Scalar c = cv::sum(*src); 758 | Scalar scal = Scalar(); 759 | scal.val1 = c.val[0]; 760 | scal.val2 = c.val[1]; 761 | scal.val3 = c.val[2]; 762 | scal.val4 = c.val[3]; 763 | return scal; 764 | } 765 | 766 | // TermCriteria_New creates a new TermCriteria 767 | TermCriteria TermCriteria_New(int typ, int maxCount, double epsilon) { 768 | return new cv::TermCriteria(typ, maxCount, epsilon); 769 | } 770 | 771 | void Contours_Close(struct Contours cs) { 772 | for (int i = 0; i < cs.length; i++) { 773 | Points_Close(cs.contours[i]); 774 | } 775 | 776 | delete[] cs.contours; 777 | } 778 | 779 | void CStrings_Close(struct CStrings cstrs) { 780 | for ( int i = 0; i < cstrs.length; i++ ) { 781 | delete [] cstrs.strs[i]; 782 | } 783 | delete [] cstrs.strs; 784 | } 785 | 786 | void KeyPoints_Close(struct KeyPoints ks) { 787 | delete[] ks.keypoints; 788 | } 789 | 790 | void Points_Close(Points ps) { 791 | for (size_t i = 0; i < ps.length; i++) { 792 | Point_Close(ps.points[i]); 793 | } 794 | 795 | delete[] ps.points; 796 | } 797 | 798 | void Point_Close(Point p) {} 799 | 800 | void Rects_Close(struct Rects rs) { 801 | delete[] rs.rects; 802 | } 803 | 804 | void DMatches_Close(struct DMatches ds) { 805 | delete[] ds.dmatches; 806 | } 807 | 808 | void MultiDMatches_Close(struct MultiDMatches mds) { 809 | for (size_t i = 0; i < mds.length; i++) { 810 | DMatches_Close(mds.dmatches[i]); 811 | } 812 | 813 | delete[] mds.dmatches; 814 | } 815 | 816 | struct DMatches MultiDMatches_get(struct MultiDMatches mds, int index) { 817 | return mds.dmatches[index]; 818 | } 819 | 820 | // since it is next to impossible to iterate over mats.mats on the cgo side 821 | Mat Mats_get(struct Mats mats, int i) { 822 | return mats.mats[i]; 823 | } 824 | 825 | void Mats_Close(struct Mats mats) { 826 | delete[] mats.mats; 827 | } 828 | 829 | void ByteArray_Release(struct ByteArray buf) { 830 | delete[] buf.data; 831 | } 832 | 833 | struct ByteArray toByteArray(const char* buf, int len) { 834 | ByteArray ret = {new char[len], len}; 835 | memcpy(ret.data, buf, len); 836 | return ret; 837 | } 838 | 839 | int64 GetCVTickCount() { 840 | return cv::getTickCount(); 841 | } 842 | 843 | double GetTickFrequency() { 844 | return cv::getTickFrequency(); 845 | } 846 | 847 | Mat Mat_rowRange(Mat m,int startrow,int endrow) { 848 | return new cv::Mat(m->rowRange(startrow,endrow)); 849 | } 850 | 851 | Mat Mat_colRange(Mat m,int startrow,int endrow) { 852 | return new cv::Mat(m->colRange(startrow,endrow)); 853 | } 854 | 855 | PointVector PointVector_New() { 856 | return new std::vector< cv::Point >; 857 | } 858 | 859 | PointVector PointVector_NewFromPoints(Contour points) { 860 | std::vector* cntr = new std::vector; 861 | 862 | for (size_t i = 0; i < points.length; i++) { 863 | cntr->push_back(cv::Point(points.points[i].x, points.points[i].y)); 864 | } 865 | 866 | return cntr; 867 | } 868 | 869 | PointVector PointVector_NewFromMat(Mat mat) { 870 | std::vector* pts = new std::vector; 871 | *pts = (std::vector) *mat; 872 | return pts; 873 | } 874 | 875 | Point PointVector_At(PointVector pv, int idx) { 876 | cv::Point p = pv->at(idx); 877 | return Point{.x = p.x, .y = p.y}; 878 | } 879 | 880 | void PointVector_Append(PointVector pv, Point p) { 881 | pv->push_back(cv::Point(p.x, p.y)); 882 | } 883 | 884 | int PointVector_Size(PointVector p) { 885 | return p->size(); 886 | } 887 | 888 | void PointVector_Close(PointVector p) { 889 | p->clear(); 890 | delete p; 891 | } 892 | 893 | PointsVector PointsVector_New() { 894 | return new std::vector< std::vector< cv::Point > >; 895 | } 896 | 897 | PointsVector PointsVector_NewFromPoints(Contours points) { 898 | std::vector< std::vector< cv::Point > >* pv = new std::vector< std::vector< cv::Point > >; 899 | 900 | for (size_t i = 0; i < points.length; i++) { 901 | Contour contour = points.contours[i]; 902 | 903 | std::vector cntr; 904 | 905 | for (size_t i = 0; i < contour.length; i++) { 906 | cntr.push_back(cv::Point(contour.points[i].x, contour.points[i].y)); 907 | } 908 | 909 | pv->push_back(cntr); 910 | } 911 | 912 | return pv; 913 | } 914 | 915 | int PointsVector_Size(PointsVector ps) { 916 | return ps->size(); 917 | } 918 | 919 | PointVector PointsVector_At(PointsVector ps, int idx) { 920 | std::vector< cv::Point >* p = &(ps->at(idx)); 921 | return p; 922 | } 923 | 924 | void PointsVector_Append(PointsVector psv, PointVector pv) { 925 | psv->push_back(*pv); 926 | } 927 | 928 | void PointsVector_Close(PointsVector ps) { 929 | ps->clear(); 930 | delete ps; 931 | } 932 | 933 | Point2fVector Point2fVector_New() { 934 | return new std::vector< cv::Point2f >; 935 | } 936 | 937 | Point2fVector Point2fVector_NewFromPoints(Contour2f points) { 938 | std::vector* cntr = new std::vector; 939 | 940 | for (size_t i = 0; i < points.length; i++) { 941 | cntr->push_back(cv::Point2f(points.points[i].x, points.points[i].y)); 942 | } 943 | 944 | return cntr; 945 | } 946 | 947 | Point2fVector Point2fVector_NewFromMat(Mat mat) { 948 | std::vector* pts = new std::vector; 949 | *pts = (std::vector) *mat; 950 | return pts; 951 | } 952 | 953 | Point2f Point2fVector_At(Point2fVector pfv, int idx) { 954 | cv::Point2f p = pfv->at(idx); 955 | return Point2f{.x = p.x, .y = p.y}; 956 | } 957 | 958 | int Point2fVector_Size(Point2fVector pfv) { 959 | return pfv->size(); 960 | } 961 | 962 | void Point2fVector_Close(Point2fVector pv) { 963 | pv->clear(); 964 | delete pv; 965 | } 966 | 967 | 968 | void IntVector_Close(struct IntVector ivec) { 969 | delete[] ivec.val; 970 | } 971 | 972 | RNG TheRNG() { 973 | return &cv::theRNG(); 974 | } 975 | 976 | void SetRNGSeed(int seed) { 977 | cv::setRNGSeed(seed); 978 | } 979 | 980 | void RNG_Fill(RNG rng, Mat mat, int distType, double a, double b, bool saturateRange) { 981 | rng->fill(*mat, distType, a, b, saturateRange); 982 | } 983 | 984 | double RNG_Gaussian(RNG rng, double sigma) { 985 | return rng->gaussian(sigma); 986 | } 987 | 988 | unsigned int RNG_Next(RNG rng) { 989 | return rng->next(); 990 | } 991 | 992 | void RandN(Mat mat, Scalar mean, Scalar stddev) { 993 | cv::Scalar m = cv::Scalar(mean.val1, mean.val2, mean.val3, mean.val4); 994 | cv::Scalar s = cv::Scalar(stddev.val1, stddev.val2, stddev.val3, stddev.val4); 995 | cv::randn(*mat, m, s); 996 | } 997 | 998 | void RandShuffle(Mat mat) { 999 | cv::randShuffle(*mat); 1000 | } 1001 | 1002 | void RandShuffleWithParams(Mat mat, double iterFactor, RNG rng) { 1003 | cv::randShuffle(*mat, iterFactor, rng); 1004 | } 1005 | 1006 | void RandU(Mat mat, Scalar low, Scalar high) { 1007 | cv::Scalar l = cv::Scalar(low.val1, low.val2, low.val3, low.val4); 1008 | cv::Scalar h = cv::Scalar(high.val1, high.val2, high.val3, high.val4); 1009 | cv::randn(*mat, l, h); 1010 | } 1011 | 1012 | void copyPointVectorToPoint2fVector(PointVector src, Point2fVector dest) { 1013 | for (size_t i = 0; i < src->size(); i++) { 1014 | dest->push_back(cv::Point2f(src->at(i).x, src->at(i).y)); 1015 | } 1016 | } 1017 | 1018 | void StdByteVectorInitialize(void* data) { 1019 | new (data) std::vector(); 1020 | } 1021 | 1022 | void StdByteVectorFree(void *data) { 1023 | reinterpret_cast *>(data)->~vector(); 1024 | } 1025 | 1026 | size_t StdByteVectorLen(void *data) { 1027 | return reinterpret_cast *>(data)->size(); 1028 | } 1029 | 1030 | uint8_t* StdByteVectorData(void *data) { 1031 | return reinterpret_cast *>(data)->data(); 1032 | } 1033 | 1034 | Points2fVector Points2fVector_New(){ 1035 | return new std::vector< std::vector< cv::Point2f > >; 1036 | } 1037 | 1038 | Points2fVector Points2fVector_NewFromPoints(Contours2f points) { 1039 | Points2fVector pv = Points2fVector_New(); 1040 | for(size_t i = 0;isize(); 1051 | } 1052 | 1053 | Point2fVector Points2fVector_At(Points2fVector ps, int idx) { 1054 | return &(ps->at(idx)); 1055 | } 1056 | 1057 | void Points2fVector_Append(Points2fVector psv, Point2fVector pv) { 1058 | psv->push_back(*pv); 1059 | } 1060 | 1061 | void Points2fVector_Close(Points2fVector ps) { 1062 | ps->clear(); 1063 | delete ps; 1064 | } 1065 | 1066 | Point3fVector Point3fVector_New() { 1067 | return new std::vector< cv::Point3f >; 1068 | } 1069 | 1070 | 1071 | Point3fVector Point3fVector_NewFromPoints(Contour3f points) { 1072 | std::vector *cntr = new std::vector; 1073 | for(size_t i = 0;i< points.length;i++) { 1074 | cntr->push_back(cv::Point3f( 1075 | points.points[i].x, 1076 | points.points[i].y, 1077 | points.points[i].z 1078 | )); 1079 | } 1080 | 1081 | return cntr; 1082 | } 1083 | 1084 | Point3fVector Point3fVector_NewFromMat(Mat mat) { 1085 | std::vector *pts = new std::vector; 1086 | *pts = (std::vector) *mat; 1087 | return pts; 1088 | } 1089 | 1090 | Point3f Point3fVector_At(Point3fVector pfv, int idx) { 1091 | cv::Point3f p = pfv->at(idx); 1092 | return Point3f{ 1093 | .x = p.x, 1094 | .y = p.y, 1095 | .z = p.z 1096 | }; 1097 | } 1098 | 1099 | void Point3fVector_Append(Point3fVector pfv, Point3f point) { 1100 | pfv->push_back(cv::Point3f(point.x, point.y, point.z)); 1101 | } 1102 | 1103 | int Point3fVector_Size(Point3fVector pfv) { 1104 | return pfv->size(); 1105 | } 1106 | 1107 | void Point3fVector_Close(Point3fVector pv) { 1108 | pv->clear(); 1109 | delete pv; 1110 | } 1111 | 1112 | Points3fVector Points3fVector_New(){ 1113 | return new std::vector< std::vector< cv::Point3f > >; 1114 | } 1115 | 1116 | Points3fVector Points3fVector_NewFromPoints(Contours3f points) { 1117 | Points3fVector pv = Points3fVector_New(); 1118 | for(size_t i = 0;isize(); 1129 | } 1130 | 1131 | Point3fVector Points3fVector_At(Points3fVector ps, int idx) { 1132 | return &(ps->at(idx)); 1133 | } 1134 | 1135 | void Points3fVector_Append(Points3fVector psv, Point3fVector pv) { 1136 | psv->push_back(*pv); 1137 | } 1138 | 1139 | void Points3fVector_Close(Points3fVector ps) { 1140 | ps->clear(); 1141 | delete ps; 1142 | } 1143 | 1144 | -------------------------------------------------------------------------------- /gocvx/core.go: -------------------------------------------------------------------------------- 1 | package gocvx 2 | 3 | /* 4 | #include 5 | #include "core.h" 6 | */ 7 | import "C" 8 | import ( 9 | "errors" 10 | "image" 11 | //"image/color" 12 | "reflect" 13 | "unsafe" 14 | ) 15 | 16 | const ( 17 | // MatChannels1 is a single channel Mat. 18 | MatChannels1 = 0 19 | 20 | // MatChannels2 is 2 channel Mat. 21 | MatChannels2 = 8 22 | 23 | // MatChannels3 is 3 channel Mat. 24 | MatChannels3 = 16 25 | 26 | // MatChannels4 is 4 channel Mat. 27 | MatChannels4 = 24 28 | ) 29 | 30 | // MatType is the type for the various different kinds of Mat you can create. 31 | type MatType int 32 | 33 | const ( 34 | // MatTypeCV8U is a Mat of 8-bit unsigned int 35 | MatTypeCV8U MatType = 0 36 | 37 | // MatTypeCV8S is a Mat of 8-bit signed int 38 | MatTypeCV8S MatType = 1 39 | 40 | // MatTypeCV16U is a Mat of 16-bit unsigned int 41 | MatTypeCV16U MatType = 2 42 | 43 | // MatTypeCV16S is a Mat of 16-bit signed int 44 | MatTypeCV16S MatType = 3 45 | 46 | // MatTypeCV16SC2 is a Mat of 16-bit signed int with 2 channels 47 | MatTypeCV16SC2 = MatTypeCV16S + MatChannels2 48 | 49 | // MatTypeCV32S is a Mat of 32-bit signed int 50 | MatTypeCV32S MatType = 4 51 | 52 | // MatTypeCV32F is a Mat of 32-bit float 53 | MatTypeCV32F MatType = 5 54 | 55 | // MatTypeCV64F is a Mat of 64-bit float 56 | MatTypeCV64F MatType = 6 57 | 58 | // MatTypeCV8UC1 is a Mat of 8-bit unsigned int with a single channel 59 | MatTypeCV8UC1 = MatTypeCV8U + MatChannels1 60 | 61 | // MatTypeCV8UC2 is a Mat of 8-bit unsigned int with 2 channels 62 | MatTypeCV8UC2 = MatTypeCV8U + MatChannels2 63 | 64 | // MatTypeCV8UC3 is a Mat of 8-bit unsigned int with 3 channels 65 | MatTypeCV8UC3 = MatTypeCV8U + MatChannels3 66 | 67 | // MatTypeCV8UC4 is a Mat of 8-bit unsigned int with 4 channels 68 | MatTypeCV8UC4 = MatTypeCV8U + MatChannels4 69 | 70 | // MatTypeCV8SC1 is a Mat of 8-bit signed int with a single channel 71 | MatTypeCV8SC1 = MatTypeCV8S + MatChannels1 72 | 73 | // MatTypeCV8SC2 is a Mat of 8-bit signed int with 2 channels 74 | MatTypeCV8SC2 = MatTypeCV8S + MatChannels2 75 | 76 | // MatTypeCV8SC3 is a Mat of 8-bit signed int with 3 channels 77 | MatTypeCV8SC3 = MatTypeCV8S + MatChannels3 78 | 79 | // MatTypeCV8SC4 is a Mat of 8-bit signed int with 4 channels 80 | MatTypeCV8SC4 = MatTypeCV8S + MatChannels4 81 | 82 | // MatTypeCV16UC1 is a Mat of 16-bit unsigned int with a single channel 83 | MatTypeCV16UC1 = MatTypeCV16U + MatChannels1 84 | 85 | // MatTypeCV16UC2 is a Mat of 16-bit unsigned int with 2 channels 86 | MatTypeCV16UC2 = MatTypeCV16U + MatChannels2 87 | 88 | // MatTypeCV16UC3 is a Mat of 16-bit unsigned int with 3 channels 89 | MatTypeCV16UC3 = MatTypeCV16U + MatChannels3 90 | 91 | // MatTypeCV16UC4 is a Mat of 16-bit unsigned int with 4 channels 92 | MatTypeCV16UC4 = MatTypeCV16U + MatChannels4 93 | 94 | // MatTypeCV16SC1 is a Mat of 16-bit signed int with a single channel 95 | MatTypeCV16SC1 = MatTypeCV16S + MatChannels1 96 | 97 | // MatTypeCV16SC3 is a Mat of 16-bit signed int with 3 channels 98 | MatTypeCV16SC3 = MatTypeCV16S + MatChannels3 99 | 100 | // MatTypeCV16SC4 is a Mat of 16-bit signed int with 4 channels 101 | MatTypeCV16SC4 = MatTypeCV16S + MatChannels4 102 | 103 | // MatTypeCV32SC1 is a Mat of 32-bit signed int with a single channel 104 | MatTypeCV32SC1 = MatTypeCV32S + MatChannels1 105 | 106 | // MatTypeCV32SC2 is a Mat of 32-bit signed int with 2 channels 107 | MatTypeCV32SC2 = MatTypeCV32S + MatChannels2 108 | 109 | // MatTypeCV32SC3 is a Mat of 32-bit signed int with 3 channels 110 | MatTypeCV32SC3 = MatTypeCV32S + MatChannels3 111 | 112 | // MatTypeCV32SC4 is a Mat of 32-bit signed int with 4 channels 113 | MatTypeCV32SC4 = MatTypeCV32S + MatChannels4 114 | 115 | // MatTypeCV32FC1 is a Mat of 32-bit float int with a single channel 116 | MatTypeCV32FC1 = MatTypeCV32F + MatChannels1 117 | 118 | // MatTypeCV32FC2 is a Mat of 32-bit float int with 2 channels 119 | MatTypeCV32FC2 = MatTypeCV32F + MatChannels2 120 | 121 | // MatTypeCV32FC3 is a Mat of 32-bit float int with 3 channels 122 | MatTypeCV32FC3 = MatTypeCV32F + MatChannels3 123 | 124 | // MatTypeCV32FC4 is a Mat of 32-bit float int with 4 channels 125 | MatTypeCV32FC4 = MatTypeCV32F + MatChannels4 126 | 127 | // MatTypeCV64FC1 is a Mat of 64-bit float int with a single channel 128 | MatTypeCV64FC1 = MatTypeCV64F + MatChannels1 129 | 130 | // MatTypeCV64FC2 is a Mat of 64-bit float int with 2 channels 131 | MatTypeCV64FC2 = MatTypeCV64F + MatChannels2 132 | 133 | // MatTypeCV64FC3 is a Mat of 64-bit float int with 3 channels 134 | MatTypeCV64FC3 = MatTypeCV64F + MatChannels3 135 | 136 | // MatTypeCV64FC4 is a Mat of 64-bit float int with 4 channels 137 | MatTypeCV64FC4 = MatTypeCV64F + MatChannels4 138 | ) 139 | 140 | // CompareType is used for Compare operations to indicate which kind of 141 | // comparison to use. 142 | type CompareType int 143 | 144 | const ( 145 | // CompareEQ src1 is equal to src2. 146 | CompareEQ CompareType = 0 147 | 148 | // CompareGT src1 is greater than src2. 149 | CompareGT CompareType = 1 150 | 151 | // CompareGE src1 is greater than or equal to src2. 152 | CompareGE CompareType = 2 153 | 154 | // CompareLT src1 is less than src2. 155 | CompareLT CompareType = 3 156 | 157 | // CompareLE src1 is less than or equal to src2. 158 | CompareLE CompareType = 4 159 | 160 | // CompareNE src1 is unequal to src2. 161 | CompareNE CompareType = 5 162 | ) 163 | 164 | type Point2f struct { 165 | X float32 166 | Y float32 167 | } 168 | 169 | func NewPoint2f(x, y float32) Point2f { 170 | return Point2f{x, y} 171 | } 172 | 173 | var ErrEmptyByteSlice = errors.New("empty byte array") 174 | 175 | // Mat represents an n-dimensional dense numerical single-channel 176 | // or multi-channel array. It can be used to store real or complex-valued 177 | // vectors and matrices, grayscale or color images, voxel volumes, 178 | // vector fields, point clouds, tensors, and histograms. 179 | // 180 | // For further details, please see: 181 | // http://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html 182 | // 183 | type Mat struct { 184 | p C.Mat 185 | 186 | // Non-nil if Mat was created with a []byte (using NewMatFromBytes()). Nil otherwise. 187 | d []byte 188 | } 189 | 190 | // addMatToProfile does nothing if matprofile tag is not set. 191 | func addMatToProfile(p C.Mat) { 192 | return 193 | } 194 | 195 | // newMat returns a new Mat from a C Mat 196 | func newMat(p C.Mat) Mat { 197 | return Mat{p: p} 198 | } 199 | 200 | // Close the Mat object. 201 | func (m *Mat) Close() error { 202 | C.Mat_Close(m.p) 203 | m.p = nil 204 | m.d = nil 205 | return nil 206 | } 207 | 208 | 209 | // NewMat returns a new empty Mat. 210 | func NewMat() Mat { 211 | return newMat(C.Mat_New()) 212 | } 213 | 214 | // NewMatWithSize returns a new Mat with a specific size and type. 215 | func NewMatWithSize(rows int, cols int, mt MatType) Mat { 216 | return newMat(C.Mat_NewWithSize(C.int(rows), C.int(cols), C.int(mt))) 217 | } 218 | 219 | // NewMatWithSizes returns a new multidimensional Mat with a specific size and type. 220 | func NewMatWithSizes(sizes []int, mt MatType) Mat { 221 | sizesArray := make([]C.int, len(sizes)) 222 | for i, s := range sizes { 223 | sizesArray[i] = C.int(s) 224 | } 225 | 226 | sizesIntVector := C.IntVector{ 227 | val: (*C.int)(&sizesArray[0]), 228 | length: C.int(len(sizes)), 229 | } 230 | return newMat(C.Mat_NewWithSizes(sizesIntVector, C.int(mt))) 231 | } 232 | 233 | // NewMatWithSizesWithScalar returns a new multidimensional Mat with a specific size, type and scalar value. 234 | func NewMatWithSizesWithScalar(sizes []int, mt MatType, s Scalar) Mat { 235 | csizes := []C.int{} 236 | for _, v := range sizes { 237 | csizes = append(csizes, C.int(v)) 238 | } 239 | sizesVector := C.struct_IntVector{} 240 | sizesVector.val = (*C.int)(&csizes[0]) 241 | sizesVector.length = (C.int)(len(csizes)) 242 | 243 | sVal := C.struct_Scalar{ 244 | val1: C.double(s.Val1), 245 | val2: C.double(s.Val2), 246 | val3: C.double(s.Val3), 247 | val4: C.double(s.Val4), 248 | } 249 | 250 | return newMat(C.Mat_NewWithSizesFromScalar(sizesVector, C.int(mt), sVal)) 251 | } 252 | 253 | // NewMatWithSizesWithScalar returns a new multidimensional Mat with a specific size, type and preexisting data. 254 | func NewMatWithSizesFromBytes(sizes []int, mt MatType, data []byte) (Mat, error) { 255 | cBytes, err := toByteArray(data) 256 | if err != nil { 257 | return Mat{}, err 258 | } 259 | 260 | csizes := []C.int{} 261 | for _, v := range sizes { 262 | csizes = append(csizes, C.int(v)) 263 | } 264 | sizesVector := C.struct_IntVector{} 265 | sizesVector.val = (*C.int)(&csizes[0]) 266 | sizesVector.length = (C.int)(len(csizes)) 267 | 268 | return newMat(C.Mat_NewWithSizesFromBytes(sizesVector, C.int(mt), *cBytes)), nil 269 | } 270 | 271 | // NewMatFromScalar returns a new Mat for a specific Scalar value 272 | func NewMatFromScalar(s Scalar, mt MatType) Mat { 273 | sVal := C.struct_Scalar{ 274 | val1: C.double(s.Val1), 275 | val2: C.double(s.Val2), 276 | val3: C.double(s.Val3), 277 | val4: C.double(s.Val4), 278 | } 279 | 280 | return newMat(C.Mat_NewFromScalar(sVal, C.int(mt))) 281 | } 282 | 283 | // NewMatWithSizeFromScalar returns a new Mat for a specific Scala value with a specific size and type 284 | // This simplifies creation of specific color filters or creating Mats of specific colors and sizes 285 | func NewMatWithSizeFromScalar(s Scalar, rows int, cols int, mt MatType) Mat { 286 | sVal := C.struct_Scalar{ 287 | val1: C.double(s.Val1), 288 | val2: C.double(s.Val2), 289 | val3: C.double(s.Val3), 290 | val4: C.double(s.Val4), 291 | } 292 | 293 | return newMat(C.Mat_NewWithSizeFromScalar(sVal, C.int(rows), C.int(cols), C.int(mt))) 294 | } 295 | 296 | // NewMatFromBytes returns a new Mat with a specific size and type, initialized from a []byte. 297 | func NewMatFromBytes(rows int, cols int, mt MatType, data []byte) (Mat, error) { 298 | cBytes, err := toByteArray(data) 299 | if err != nil { 300 | return Mat{}, err 301 | } 302 | mat := newMat(C.Mat_NewFromBytes(C.int(rows), C.int(cols), C.int(mt), *cBytes)) 303 | 304 | // Store a reference to the backing data slice. This is needed because we pass the backing 305 | // array directly to C code and without keeping a Go reference to it, it might end up 306 | // garbage collected which would result in crashes. 307 | // 308 | // TODO(bga): This could live in newMat() but I wanted to reduce the change surface. 309 | // TODO(bga): Code that needs access to the array from Go could use this directly. 310 | mat.d = data 311 | 312 | return mat, nil 313 | } 314 | 315 | // Returns an identity matrix of the specified size and type. 316 | // 317 | // The method returns a Matlab-style identity matrix initializer, similarly to Mat::zeros. Similarly to Mat::ones. 318 | // For further details, please see: 319 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#a2cf9b9acde7a9852542bbc20ef851ed2 320 | func Eye(rows int, cols int, mt MatType) Mat { 321 | return newMat(C.Eye(C.int(rows), C.int(cols), C.int(mt))) 322 | } 323 | 324 | // Returns a zero array of the specified size and type. 325 | // 326 | // The method returns a Matlab-style zero array initializer. 327 | // For further details, please see: 328 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#a0b57b6a326c8876d944d188a46e0f556 329 | func Zeros(rows int, cols int, mt MatType) Mat { 330 | return newMat(C.Zeros(C.int(rows), C.int(cols), C.int(mt))) 331 | } 332 | 333 | // Returns an array of all 1's of the specified size and type. 334 | // 335 | // The method returns a Matlab-style 1's array initializer 336 | // For further details, please see: 337 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#a69ae0402d116fc9c71908d8508dc2f09 338 | func Ones(rows int, cols int, mt MatType) Mat { 339 | return newMat(C.Ones(C.int(rows), C.int(cols), C.int(mt))) 340 | } 341 | 342 | // FromPtr returns a new Mat with a specific size and type, initialized from a Mat Ptr. 343 | func (m *Mat) FromPtr(rows int, cols int, mt MatType, prow int, pcol int) (Mat, error) { 344 | return newMat(C.Mat_FromPtr(m.p, C.int(rows), C.int(cols), C.int(mt), C.int(prow), C.int(pcol))), nil 345 | } 346 | 347 | // Ptr returns the Mat's underlying object pointer. 348 | func (m *Mat) Ptr() C.Mat { 349 | return m.p 350 | } 351 | 352 | // Empty determines if the Mat is empty or not. 353 | func (m *Mat) Empty() bool { 354 | isEmpty := C.Mat_Empty(m.p) 355 | return isEmpty != 0 356 | } 357 | 358 | // IsContinuous determines if the Mat is continuous. 359 | // 360 | // For further details, please see: 361 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#aa90cea495029c7d1ee0a41361ccecdf3 362 | // 363 | func (m *Mat) IsContinuous() bool { 364 | return bool(C.Mat_IsContinuous(m.p)) 365 | } 366 | 367 | // Clone returns a cloned full copy of the Mat. 368 | func (m *Mat) Clone() Mat { 369 | return newMat(C.Mat_Clone(m.p)) 370 | } 371 | 372 | // CopyTo copies Mat into destination Mat. 373 | // 374 | // For further details, please see: 375 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77 376 | // 377 | func (m *Mat) CopyTo(dst *Mat) { 378 | C.Mat_CopyTo(m.p, dst.p) 379 | return 380 | } 381 | 382 | // CopyToWithMask copies Mat into destination Mat after applying the mask Mat. 383 | // 384 | // For further details, please see: 385 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#a626fe5f96d02525e2604d2ad46dd574f 386 | // 387 | func (m *Mat) CopyToWithMask(dst *Mat, mask Mat) { 388 | C.Mat_CopyToWithMask(m.p, dst.p, mask.p) 389 | return 390 | } 391 | 392 | // ConvertTo converts Mat into destination Mat. 393 | // 394 | // For further details, please see: 395 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#adf88c60c5b4980e05bb556080916978b 396 | // 397 | func (m *Mat) ConvertTo(dst *Mat, mt MatType) { 398 | C.Mat_ConvertTo(m.p, dst.p, C.int(mt)) 399 | return 400 | } 401 | 402 | func (m *Mat) ConvertToWithParams(dst *Mat, mt MatType, alpha, beta float32) { 403 | C.Mat_ConvertToWithParams(m.p, dst.p, C.int(mt), C.float(alpha), C.float(beta)) 404 | return 405 | } 406 | 407 | // Total returns the total number of array elements. 408 | // 409 | // For further details, please see: 410 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#aa4d317d43fb0cba9c2503f3c61b866c8 411 | // 412 | func (m *Mat) Total() int { 413 | return int(C.Mat_Total(m.p)) 414 | } 415 | 416 | // Size returns an array with one element for each dimension containing the size of that dimension for the Mat. 417 | // 418 | // For further details, please see: 419 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#aa4d317d43fb0cba9c2503f3c61b866c8 420 | // 421 | func (m *Mat) Size() (dims []int) { 422 | cdims := C.IntVector{} 423 | C.Mat_Size(m.p, &cdims) 424 | defer C.IntVector_Close(cdims) 425 | 426 | h := &reflect.SliceHeader{ 427 | Data: uintptr(unsafe.Pointer(cdims.val)), 428 | Len: int(cdims.length), 429 | Cap: int(cdims.length), 430 | } 431 | pdims := *(*[]C.int)(unsafe.Pointer(h)) 432 | 433 | for i := 0; i < int(cdims.length); i++ { 434 | dims = append(dims, int(pdims[i])) 435 | } 436 | return 437 | } 438 | 439 | // ToBytes copies the underlying Mat data to a byte array. 440 | // 441 | // For further details, please see: 442 | // https://docs.opencv.org/3.3.1/d3/d63/classcv_1_1Mat.html#a4d33bed1c850265370d2af0ff02e1564 443 | func (m *Mat) ToBytes() []byte { 444 | b := C.Mat_DataPtr(m.p) 445 | return toGoBytes(b) 446 | } 447 | 448 | // DataPtrUint8 returns a slice that references the OpenCV allocated data. 449 | // 450 | // The data is no longer valid once the Mat has been closed. Any data that 451 | // needs to be accessed after the Mat is closed must be copied into Go memory. 452 | func (m *Mat) DataPtrUint8() ([]uint8, error) { 453 | if !m.IsContinuous() { 454 | return nil, errors.New("DataPtrUint8 requires continuous Mat") 455 | } 456 | 457 | p := C.Mat_DataPtr(m.p) 458 | h := &reflect.SliceHeader{ 459 | Data: uintptr(unsafe.Pointer(p.data)), 460 | Len: int(p.length), 461 | Cap: int(p.length), 462 | } 463 | return *(*[]uint8)(unsafe.Pointer(h)), nil 464 | } 465 | 466 | // DataPtrInt8 returns a slice that references the OpenCV allocated data. 467 | // 468 | // The data is no longer valid once the Mat has been closed. Any data that 469 | // needs to be accessed after the Mat is closed must be copied into Go memory. 470 | func (m *Mat) DataPtrInt8() ([]int8, error) { 471 | if m.Type()&MatTypeCV8S != MatTypeCV8S { 472 | return nil, errors.New("DataPtrInt8 only supports MatTypeCV8S") 473 | } 474 | 475 | if !m.IsContinuous() { 476 | return nil, errors.New("DataPtrInt8 requires continuous Mat") 477 | } 478 | 479 | p := C.Mat_DataPtr(m.p) 480 | h := &reflect.SliceHeader{ 481 | Data: uintptr(unsafe.Pointer(p.data)), 482 | Len: int(p.length), 483 | Cap: int(p.length), 484 | } 485 | return *(*[]int8)(unsafe.Pointer(h)), nil 486 | } 487 | 488 | // DataPtrUint16 returns a slice that references the OpenCV allocated data. 489 | // 490 | // The data is no longer valid once the Mat has been closed. Any data that 491 | // needs to be accessed after the Mat is closed must be copied into Go memory. 492 | func (m *Mat) DataPtrUint16() ([]uint16, error) { 493 | if m.Type()&MatTypeCV16U != MatTypeCV16U { 494 | return nil, errors.New("DataPtrUint16 only supports MatTypeCV16U") 495 | } 496 | 497 | if !m.IsContinuous() { 498 | return nil, errors.New("DataPtrUint16 requires continuous Mat") 499 | } 500 | 501 | p := C.Mat_DataPtr(m.p) 502 | h := &reflect.SliceHeader{ 503 | Data: uintptr(unsafe.Pointer(p.data)), 504 | Len: int(p.length) / 2, 505 | Cap: int(p.length) / 2, 506 | } 507 | return *(*[]uint16)(unsafe.Pointer(h)), nil 508 | } 509 | 510 | // DataPtrInt16 returns a slice that references the OpenCV allocated data. 511 | // 512 | // The data is no longer valid once the Mat has been closed. Any data that 513 | // needs to be accessed after the Mat is closed must be copied into Go memory. 514 | func (m *Mat) DataPtrInt16() ([]int16, error) { 515 | if m.Type()&MatTypeCV16S != MatTypeCV16S { 516 | return nil, errors.New("DataPtrInt16 only supports MatTypeCV16S") 517 | } 518 | 519 | if !m.IsContinuous() { 520 | return nil, errors.New("DataPtrInt16 requires continuous Mat") 521 | } 522 | 523 | p := C.Mat_DataPtr(m.p) 524 | h := &reflect.SliceHeader{ 525 | Data: uintptr(unsafe.Pointer(p.data)), 526 | Len: int(p.length) / 2, 527 | Cap: int(p.length) / 2, 528 | } 529 | return *(*[]int16)(unsafe.Pointer(h)), nil 530 | } 531 | 532 | // DataPtrFloat32 returns a slice that references the OpenCV allocated data. 533 | // 534 | // The data is no longer valid once the Mat has been closed. Any data that 535 | // needs to be accessed after the Mat is closed must be copied into Go memory. 536 | func (m *Mat) DataPtrFloat32() ([]float32, error) { 537 | if m.Type()&MatTypeCV32F != MatTypeCV32F { 538 | return nil, errors.New("DataPtrFloat32 only supports MatTypeCV32F") 539 | } 540 | 541 | if !m.IsContinuous() { 542 | return nil, errors.New("DataPtrFloat32 requires continuous Mat") 543 | } 544 | 545 | p := C.Mat_DataPtr(m.p) 546 | h := &reflect.SliceHeader{ 547 | Data: uintptr(unsafe.Pointer(p.data)), 548 | Len: int(p.length) / 4, 549 | Cap: int(p.length) / 4, 550 | } 551 | return *(*[]float32)(unsafe.Pointer(h)), nil 552 | } 553 | 554 | // DataPtrFloat64 returns a slice that references the OpenCV allocated data. 555 | // 556 | // The data is no longer valid once the Mat has been closed. Any data that 557 | // needs to be accessed after the Mat is closed must be copied into Go memory. 558 | func (m *Mat) DataPtrFloat64() ([]float64, error) { 559 | if m.Type()&MatTypeCV64F != MatTypeCV64F { 560 | return nil, errors.New("DataPtrFloat64 only supports MatTypeCV64F") 561 | } 562 | 563 | if !m.IsContinuous() { 564 | return nil, errors.New("DataPtrFloat64 requires continuous Mat") 565 | } 566 | 567 | p := C.Mat_DataPtr(m.p) 568 | h := &reflect.SliceHeader{ 569 | Data: uintptr(unsafe.Pointer(p.data)), 570 | Len: int(p.length) / 8, 571 | Cap: int(p.length) / 8, 572 | } 573 | return *(*[]float64)(unsafe.Pointer(h)), nil 574 | } 575 | 576 | // Region returns a new Mat that points to a region of this Mat. Changes made to the 577 | // region Mat will affect the original Mat, since they are pointers to the underlying 578 | // OpenCV Mat object. 579 | func (m *Mat) Region(rio image.Rectangle) Mat { 580 | cRect := C.struct_Rect{ 581 | x: C.int(rio.Min.X), 582 | y: C.int(rio.Min.Y), 583 | width: C.int(rio.Size().X), 584 | height: C.int(rio.Size().Y), 585 | } 586 | 587 | return newMat(C.Mat_Region(m.p, cRect)) 588 | } 589 | 590 | // Reshape changes the shape and/or the number of channels of a 2D matrix without copying the data. 591 | // 592 | // For further details, please see: 593 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#a4eb96e3251417fa88b78e2abd6cfd7d8 594 | // 595 | func (m *Mat) Reshape(cn int, rows int) Mat { 596 | return newMat(C.Mat_Reshape(m.p, C.int(cn), C.int(rows))) 597 | } 598 | 599 | // ConvertFp16 converts a Mat to half-precision floating point. 600 | // 601 | // For further details, please see: 602 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga9c25d9ef44a2a48ecc3774b30cb80082 603 | // 604 | func (m *Mat) ConvertFp16() Mat { 605 | return newMat(C.Mat_ConvertFp16(m.p)) 606 | } 607 | 608 | // Mean calculates the mean value M of array elements, independently for each channel, and return it as Scalar 609 | // For further details, please see: 610 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga191389f8a0e58180bb13a727782cd461 611 | // 612 | func (m *Mat) Mean() Scalar { 613 | s := C.Mat_Mean(m.p) 614 | return NewScalar(float64(s.val1), float64(s.val2), float64(s.val3), float64(s.val4)) 615 | } 616 | 617 | // MeanWithMask calculates the mean value M of array elements,independently for each channel, 618 | // and returns it as Scalar vector while applying the mask. 619 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga191389f8a0e58180bb13a727782cd461 620 | // 621 | func (m *Mat) MeanWithMask(mask Mat) Scalar { 622 | s := C.Mat_MeanWithMask(m.p, mask.p) 623 | return NewScalar(float64(s.val1), float64(s.val2), float64(s.val3), float64(s.val4)) 624 | } 625 | 626 | // Sqrt calculates a square root of array elements. 627 | // 628 | // For further details, please see: 629 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga186222c3919657890f88df5a1f64a7d7 630 | // 631 | func (m *Mat) Sqrt() Mat { 632 | return newMat(C.Mat_Sqrt(m.p)) 633 | } 634 | 635 | // Sum calculates the per-channel pixel sum of an image. 636 | // 637 | // For further details, please see: 638 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga716e10a2dd9e228e4d3c95818f106722 639 | // 640 | func (m *Mat) Sum() Scalar { 641 | s := C.Mat_Sum(m.p) 642 | return NewScalar(float64(s.val1), float64(s.val2), float64(s.val3), float64(s.val4)) 643 | } 644 | 645 | // PatchNaNs converts NaN's to zeros. 646 | // 647 | // For further details, please see: 648 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga62286befb7cde3568ff8c7d14d5079da 649 | // 650 | func (m *Mat) PatchNaNs() { 651 | C.Mat_PatchNaNs(m.p) 652 | } 653 | 654 | // LUT performs a look-up table transform of an array. 655 | // 656 | // The function LUT fills the output array with values from the look-up table. 657 | // Indices of the entries are taken from the input array. 658 | // 659 | // For further details, please see: 660 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gab55b8d062b7f5587720ede032d34156f 661 | func LUT(src, wbLUT Mat, dst *Mat) { 662 | C.LUT(src.p, wbLUT.p, dst.p) 663 | } 664 | 665 | // Rows returns the number of rows for this Mat. 666 | func (m *Mat) Rows() int { 667 | return int(C.Mat_Rows(m.p)) 668 | } 669 | 670 | // Cols returns the number of columns for this Mat. 671 | func (m *Mat) Cols() int { 672 | return int(C.Mat_Cols(m.p)) 673 | } 674 | 675 | // Channels returns the number of channels for this Mat. 676 | func (m *Mat) Channels() int { 677 | return int(C.Mat_Channels(m.p)) 678 | } 679 | 680 | // Type returns the type for this Mat. 681 | func (m *Mat) Type() MatType { 682 | return MatType(C.Mat_Type(m.p)) 683 | } 684 | 685 | // Step returns the number of bytes each matrix row occupies. 686 | func (m *Mat) Step() int { 687 | return int(C.Mat_Step(m.p)) 688 | } 689 | 690 | // GetUCharAt returns a value from a specific row/col 691 | // in this Mat expecting it to be of type uchar aka CV_8U. 692 | func (m *Mat) GetUCharAt(row int, col int) uint8 { 693 | return uint8(C.Mat_GetUChar(m.p, C.int(row), C.int(col))) 694 | } 695 | 696 | // GetUCharAt3 returns a value from a specific x, y, z coordinate location 697 | // in this Mat expecting it to be of type uchar aka CV_8U. 698 | func (m *Mat) GetUCharAt3(x, y, z int) uint8 { 699 | return uint8(C.Mat_GetUChar3(m.p, C.int(x), C.int(y), C.int(z))) 700 | } 701 | 702 | // GetSCharAt returns a value from a specific row/col 703 | // in this Mat expecting it to be of type schar aka CV_8S. 704 | func (m *Mat) GetSCharAt(row int, col int) int8 { 705 | return int8(C.Mat_GetSChar(m.p, C.int(row), C.int(col))) 706 | } 707 | 708 | // GetSCharAt3 returns a value from a specific x, y, z coordinate location 709 | // in this Mat expecting it to be of type schar aka CV_8S. 710 | func (m *Mat) GetSCharAt3(x, y, z int) int8 { 711 | return int8(C.Mat_GetSChar3(m.p, C.int(x), C.int(y), C.int(z))) 712 | } 713 | 714 | // GetShortAt returns a value from a specific row/col 715 | // in this Mat expecting it to be of type short aka CV_16S. 716 | func (m *Mat) GetShortAt(row int, col int) int16 { 717 | return int16(C.Mat_GetShort(m.p, C.int(row), C.int(col))) 718 | } 719 | 720 | // GetShortAt3 returns a value from a specific x, y, z coordinate location 721 | // in this Mat expecting it to be of type short aka CV_16S. 722 | func (m *Mat) GetShortAt3(x, y, z int) int16 { 723 | return int16(C.Mat_GetShort3(m.p, C.int(x), C.int(y), C.int(z))) 724 | } 725 | 726 | // GetIntAt returns a value from a specific row/col 727 | // in this Mat expecting it to be of type int aka CV_32S. 728 | func (m *Mat) GetIntAt(row int, col int) int32 { 729 | return int32(C.Mat_GetInt(m.p, C.int(row), C.int(col))) 730 | } 731 | 732 | // GetIntAt3 returns a value from a specific x, y, z coordinate location 733 | // in this Mat expecting it to be of type int aka CV_32S. 734 | func (m *Mat) GetIntAt3(x, y, z int) int32 { 735 | return int32(C.Mat_GetInt3(m.p, C.int(x), C.int(y), C.int(z))) 736 | } 737 | 738 | // GetFloatAt returns a value from a specific row/col 739 | // in this Mat expecting it to be of type float aka CV_32F. 740 | func (m *Mat) GetFloatAt(row int, col int) float32 { 741 | return float32(C.Mat_GetFloat(m.p, C.int(row), C.int(col))) 742 | } 743 | 744 | // GetFloatAt3 returns a value from a specific x, y, z coordinate location 745 | // in this Mat expecting it to be of type float aka CV_32F. 746 | func (m *Mat) GetFloatAt3(x, y, z int) float32 { 747 | return float32(C.Mat_GetFloat3(m.p, C.int(x), C.int(y), C.int(z))) 748 | } 749 | 750 | // GetDoubleAt returns a value from a specific row/col 751 | // in this Mat expecting it to be of type double aka CV_64F. 752 | func (m *Mat) GetDoubleAt(row int, col int) float64 { 753 | return float64(C.Mat_GetDouble(m.p, C.int(row), C.int(col))) 754 | } 755 | 756 | // GetDoubleAt3 returns a value from a specific x, y, z coordinate location 757 | // in this Mat expecting it to be of type double aka CV_64F. 758 | func (m *Mat) GetDoubleAt3(x, y, z int) float64 { 759 | return float64(C.Mat_GetDouble3(m.p, C.int(x), C.int(y), C.int(z))) 760 | } 761 | 762 | // SetTo sets all or some of the array elements to the specified scalar value. 763 | func (m *Mat) SetTo(s Scalar) { 764 | sVal := C.struct_Scalar{ 765 | val1: C.double(s.Val1), 766 | val2: C.double(s.Val2), 767 | val3: C.double(s.Val3), 768 | val4: C.double(s.Val4), 769 | } 770 | 771 | C.Mat_SetTo(m.p, sVal) 772 | } 773 | 774 | // SetUCharAt sets a value at a specific row/col 775 | // in this Mat expecting it to be of type uchar aka CV_8U. 776 | func (m *Mat) SetUCharAt(row int, col int, val uint8) { 777 | C.Mat_SetUChar(m.p, C.int(row), C.int(col), C.uint8_t(val)) 778 | } 779 | 780 | // SetUCharAt3 sets a value at a specific x, y, z coordinate location 781 | // in this Mat expecting it to be of type uchar aka CV_8U. 782 | func (m *Mat) SetUCharAt3(x, y, z int, val uint8) { 783 | C.Mat_SetUChar3(m.p, C.int(x), C.int(y), C.int(z), C.uint8_t(val)) 784 | } 785 | 786 | // SetSCharAt sets a value at a specific row/col 787 | // in this Mat expecting it to be of type schar aka CV_8S. 788 | func (m *Mat) SetSCharAt(row int, col int, val int8) { 789 | C.Mat_SetSChar(m.p, C.int(row), C.int(col), C.int8_t(val)) 790 | } 791 | 792 | // SetSCharAt3 sets a value at a specific x, y, z coordinate location 793 | // in this Mat expecting it to be of type schar aka CV_8S. 794 | func (m *Mat) SetSCharAt3(x, y, z int, val int8) { 795 | C.Mat_SetSChar3(m.p, C.int(x), C.int(y), C.int(z), C.int8_t(val)) 796 | } 797 | 798 | // SetShortAt sets a value at a specific row/col 799 | // in this Mat expecting it to be of type short aka CV_16S. 800 | func (m *Mat) SetShortAt(row int, col int, val int16) { 801 | C.Mat_SetShort(m.p, C.int(row), C.int(col), C.int16_t(val)) 802 | } 803 | 804 | // SetShortAt3 sets a value at a specific x, y, z coordinate location 805 | // in this Mat expecting it to be of type short aka CV_16S. 806 | func (m *Mat) SetShortAt3(x, y, z int, val int16) { 807 | C.Mat_SetShort3(m.p, C.int(x), C.int(y), C.int(z), C.int16_t(val)) 808 | } 809 | 810 | // SetIntAt sets a value at a specific row/col 811 | // in this Mat expecting it to be of type int aka CV_32S. 812 | func (m *Mat) SetIntAt(row int, col int, val int32) { 813 | C.Mat_SetInt(m.p, C.int(row), C.int(col), C.int32_t(val)) 814 | } 815 | 816 | // SetIntAt3 sets a value at a specific x, y, z coordinate location 817 | // in this Mat expecting it to be of type int aka CV_32S. 818 | func (m *Mat) SetIntAt3(x, y, z int, val int32) { 819 | C.Mat_SetInt3(m.p, C.int(x), C.int(y), C.int(z), C.int32_t(val)) 820 | } 821 | 822 | // SetFloatAt sets a value at a specific row/col 823 | // in this Mat expecting it to be of type float aka CV_32F. 824 | func (m *Mat) SetFloatAt(row int, col int, val float32) { 825 | C.Mat_SetFloat(m.p, C.int(row), C.int(col), C.float(val)) 826 | } 827 | 828 | // SetFloatAt3 sets a value at a specific x, y, z coordinate location 829 | // in this Mat expecting it to be of type float aka CV_32F. 830 | func (m *Mat) SetFloatAt3(x, y, z int, val float32) { 831 | C.Mat_SetFloat3(m.p, C.int(x), C.int(y), C.int(z), C.float(val)) 832 | } 833 | 834 | // SetDoubleAt sets a value at a specific row/col 835 | // in this Mat expecting it to be of type double aka CV_64F. 836 | func (m *Mat) SetDoubleAt(row int, col int, val float64) { 837 | C.Mat_SetDouble(m.p, C.int(row), C.int(col), C.double(val)) 838 | } 839 | 840 | // SetDoubleAt3 sets a value at a specific x, y, z coordinate location 841 | // in this Mat expecting it to be of type double aka CV_64F. 842 | func (m *Mat) SetDoubleAt3(x, y, z int, val float64) { 843 | C.Mat_SetDouble3(m.p, C.int(x), C.int(y), C.int(z), C.double(val)) 844 | } 845 | 846 | // AddUChar adds a uchar value to each element in the Mat. Performs a 847 | // mat += val operation. 848 | func (m *Mat) AddUChar(val uint8) { 849 | C.Mat_AddUChar(m.p, C.uint8_t(val)) 850 | } 851 | 852 | // SubtractUChar subtracts a uchar value from each element in the Mat. Performs a 853 | // mat -= val operation. 854 | func (m *Mat) SubtractUChar(val uint8) { 855 | C.Mat_SubtractUChar(m.p, C.uint8_t(val)) 856 | } 857 | 858 | // MultiplyUChar multiplies each element in the Mat by a uint value. Performs a 859 | // mat *= val operation. 860 | func (m *Mat) MultiplyUChar(val uint8) { 861 | C.Mat_MultiplyUChar(m.p, C.uint8_t(val)) 862 | } 863 | 864 | // DivideUChar divides each element in the Mat by a uint value. Performs a 865 | // mat /= val operation. 866 | func (m *Mat) DivideUChar(val uint8) { 867 | C.Mat_DivideUChar(m.p, C.uint8_t(val)) 868 | } 869 | 870 | // AddFloat adds a float value to each element in the Mat. Performs a 871 | // mat += val operation. 872 | func (m *Mat) AddFloat(val float32) { 873 | C.Mat_AddFloat(m.p, C.float(val)) 874 | } 875 | 876 | // SubtractFloat subtracts a float value from each element in the Mat. Performs a 877 | // mat -= val operation. 878 | func (m *Mat) SubtractFloat(val float32) { 879 | C.Mat_SubtractFloat(m.p, C.float(val)) 880 | } 881 | 882 | // MultiplyFloat multiplies each element in the Mat by a float value. Performs a 883 | // mat *= val operation. 884 | func (m *Mat) MultiplyFloat(val float32) { 885 | C.Mat_MultiplyFloat(m.p, C.float(val)) 886 | } 887 | 888 | // DivideFloat divides each element in the Mat by a float value. Performs a 889 | // mat /= val operation. 890 | func (m *Mat) DivideFloat(val float32) { 891 | C.Mat_DivideFloat(m.p, C.float(val)) 892 | } 893 | 894 | // MultiplyMatrix multiplies matrix (m*x) 895 | func (m *Mat) MultiplyMatrix(x Mat) Mat { 896 | return newMat(C.Mat_MultiplyMatrix(m.p, x.p)) 897 | } 898 | 899 | // T transpose matrix 900 | // https://docs.opencv.org/4.1.2/d3/d63/classcv_1_1Mat.html#aaa428c60ccb6d8ea5de18f63dfac8e11 901 | func (m *Mat) T() Mat { 902 | return newMat(C.Mat_T(m.p)) 903 | } 904 | 905 | // AbsDiff calculates the per-element absolute difference between two arrays 906 | // or between an array and a scalar. 907 | // 908 | // For further details, please see: 909 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga6fef31bc8c4071cbc114a758a2b79c14 910 | // 911 | func AbsDiff(src1, src2 Mat, dst *Mat) { 912 | C.Mat_AbsDiff(src1.p, src2.p, dst.p) 913 | } 914 | 915 | // Add calculates the per-element sum of two arrays or an array and a scalar. 916 | // 917 | // For further details, please see: 918 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga10ac1bfb180e2cfda1701d06c24fdbd6 919 | // 920 | func Add(src1, src2 Mat, dst *Mat) { 921 | C.Mat_Add(src1.p, src2.p, dst.p) 922 | } 923 | 924 | // AddWeighted calculates the weighted sum of two arrays. 925 | // 926 | // For further details, please see: 927 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gafafb2513349db3bcff51f54ee5592a19 928 | // 929 | func AddWeighted(src1 Mat, alpha float64, src2 Mat, beta float64, gamma float64, dst *Mat) { 930 | C.Mat_AddWeighted(src1.p, C.double(alpha), 931 | src2.p, C.double(beta), C.double(gamma), dst.p) 932 | } 933 | 934 | // BitwiseAnd computes bitwise conjunction of the two arrays (dst = src1 & src2). 935 | // Calculates the per-element bit-wise conjunction of two arrays 936 | // or an array and a scalar. 937 | // 938 | // For further details, please see: 939 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga60b4d04b251ba5eb1392c34425497e14 940 | // 941 | func BitwiseAnd(src1 Mat, src2 Mat, dst *Mat) { 942 | C.Mat_BitwiseAnd(src1.p, src2.p, dst.p) 943 | } 944 | 945 | // BitwiseAndWithMask computes bitwise conjunction of the two arrays (dst = src1 & src2). 946 | // Calculates the per-element bit-wise conjunction of two arrays 947 | // or an array and a scalar. It has an additional parameter for a mask. 948 | // 949 | // For further details, please see: 950 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga60b4d04b251ba5eb1392c34425497e14 951 | // 952 | func BitwiseAndWithMask(src1 Mat, src2 Mat, dst *Mat, mask Mat) { 953 | C.Mat_BitwiseAndWithMask(src1.p, src2.p, dst.p, mask.p) 954 | } 955 | 956 | // BitwiseNot inverts every bit of an array. 957 | // 958 | // For further details, please see: 959 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga0002cf8b418479f4cb49a75442baee2f 960 | // 961 | func BitwiseNot(src1 Mat, dst *Mat) { 962 | C.Mat_BitwiseNot(src1.p, dst.p) 963 | } 964 | 965 | // BitwiseNotWithMask inverts every bit of an array. It has an additional parameter for a mask. 966 | // 967 | // For further details, please see: 968 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga0002cf8b418479f4cb49a75442baee2f 969 | // 970 | func BitwiseNotWithMask(src1 Mat, dst *Mat, mask Mat) { 971 | C.Mat_BitwiseNotWithMask(src1.p, dst.p, mask.p) 972 | } 973 | 974 | // BitwiseOr calculates the per-element bit-wise disjunction of two arrays 975 | // or an array and a scalar. 976 | // 977 | // For further details, please see: 978 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gab85523db362a4e26ff0c703793a719b4 979 | // 980 | func BitwiseOr(src1 Mat, src2 Mat, dst *Mat) { 981 | C.Mat_BitwiseOr(src1.p, src2.p, dst.p) 982 | } 983 | 984 | // BitwiseOrWithMask calculates the per-element bit-wise disjunction of two arrays 985 | // or an array and a scalar. It has an additional parameter for a mask. 986 | // 987 | // For further details, please see: 988 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gab85523db362a4e26ff0c703793a719b4 989 | // 990 | func BitwiseOrWithMask(src1 Mat, src2 Mat, dst *Mat, mask Mat) { 991 | C.Mat_BitwiseOrWithMask(src1.p, src2.p, dst.p, mask.p) 992 | } 993 | 994 | // BitwiseXor calculates the per-element bit-wise "exclusive or" operation 995 | // on two arrays or an array and a scalar. 996 | // 997 | // For further details, please see: 998 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga84b2d8188ce506593dcc3f8cd00e8e2c 999 | // 1000 | func BitwiseXor(src1 Mat, src2 Mat, dst *Mat) { 1001 | C.Mat_BitwiseXor(src1.p, src2.p, dst.p) 1002 | } 1003 | 1004 | // BitwiseXorWithMask calculates the per-element bit-wise "exclusive or" operation 1005 | // on two arrays or an array and a scalar. It has an additional parameter for a mask. 1006 | // 1007 | // For further details, please see: 1008 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga84b2d8188ce506593dcc3f8cd00e8e2c 1009 | // 1010 | func BitwiseXorWithMask(src1 Mat, src2 Mat, dst *Mat, mask Mat) { 1011 | C.Mat_BitwiseXorWithMask(src1.p, src2.p, dst.p, mask.p) 1012 | } 1013 | 1014 | // BatchDistance is a naive nearest neighbor finder. 1015 | // 1016 | // For further details, please see: 1017 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga4ba778a1c57f83233b1d851c83f5a622 1018 | // 1019 | func BatchDistance(src1 Mat, src2 Mat, dist Mat, dtype MatType, nidx Mat, normType NormType, K int, mask Mat, update int, crosscheck bool) { 1020 | C.Mat_BatchDistance(src1.p, src2.p, dist.p, C.int(dtype), nidx.p, C.int(normType), C.int(K), mask.p, C.int(update), C.bool(crosscheck)) 1021 | } 1022 | 1023 | // BorderInterpolate computes the source location of an extrapolated pixel. 1024 | // 1025 | // For further details, please see: 1026 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga247f571aa6244827d3d798f13892da58 1027 | // 1028 | func BorderInterpolate(p int, len int, borderType CovarFlags) int { 1029 | ret := C.Mat_BorderInterpolate(C.int(p), C.int(len), C.int(borderType)) 1030 | return int(ret) 1031 | } 1032 | 1033 | // CovarFlags are the covariation flags used by functions such as BorderInterpolate. 1034 | // 1035 | // For further details, please see: 1036 | // https://docs.opencv.org/master/d0/de1/group__core.html#ga719ebd4a73f30f4fab258ab7616d0f0f 1037 | // 1038 | type CovarFlags int 1039 | 1040 | const ( 1041 | // CovarScrambled indicates to scramble the results. 1042 | CovarScrambled CovarFlags = 0 1043 | 1044 | // CovarNormal indicates to use normal covariation. 1045 | CovarNormal CovarFlags = 1 1046 | 1047 | // CovarUseAvg indicates to use average covariation. 1048 | CovarUseAvg CovarFlags = 2 1049 | 1050 | // CovarScale indicates to use scaled covariation. 1051 | CovarScale CovarFlags = 4 1052 | 1053 | // CovarRows indicates to use covariation on rows. 1054 | CovarRows CovarFlags = 8 1055 | 1056 | // CovarCols indicates to use covariation on columns. 1057 | CovarCols CovarFlags = 16 1058 | ) 1059 | 1060 | // CalcCovarMatrix calculates the covariance matrix of a set of vectors. 1061 | // 1062 | // For further details, please see: 1063 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga017122d912af19d7d0d2cccc2d63819f 1064 | // 1065 | func CalcCovarMatrix(samples Mat, covar *Mat, mean *Mat, flags CovarFlags, ctype MatType) { 1066 | C.Mat_CalcCovarMatrix(samples.p, covar.p, mean.p, C.int(flags), C.int(ctype)) 1067 | } 1068 | 1069 | // CartToPolar calculates the magnitude and angle of 2D vectors. 1070 | // 1071 | // For further details, please see: 1072 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gac5f92f48ec32cacf5275969c33ee837d 1073 | // 1074 | func CartToPolar(x Mat, y Mat, magnitude *Mat, angle *Mat, angleInDegrees bool) { 1075 | C.Mat_CartToPolar(x.p, y.p, magnitude.p, angle.p, C.bool(angleInDegrees)) 1076 | } 1077 | 1078 | // CheckRange checks every element of an input array for invalid values. 1079 | // 1080 | // For further details, please see: 1081 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga2bd19d89cae59361416736f87e3c7a64 1082 | // 1083 | func CheckRange(src Mat) bool { 1084 | return bool(C.Mat_CheckRange(src.p)) 1085 | } 1086 | 1087 | // Compare performs the per-element comparison of two arrays 1088 | // or an array and scalar value. 1089 | // 1090 | // For further details, please see: 1091 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga303cfb72acf8cbb36d884650c09a3a97 1092 | // 1093 | func Compare(src1 Mat, src2 Mat, dst *Mat, ct CompareType) { 1094 | C.Mat_Compare(src1.p, src2.p, dst.p, C.int(ct)) 1095 | } 1096 | 1097 | // CountNonZero counts non-zero array elements. 1098 | // 1099 | // For further details, please see: 1100 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaa4b89393263bb4d604e0fe5986723914 1101 | // 1102 | func CountNonZero(src Mat) int { 1103 | return int(C.Mat_CountNonZero(src.p)) 1104 | } 1105 | 1106 | // CompleteSymm copies the lower or the upper half of a square matrix to its another half. 1107 | // 1108 | // For further details, please see: 1109 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaa9d88dcd0e54b6d1af38d41f2a3e3d25 1110 | // 1111 | func CompleteSymm(m Mat, lowerToUpper bool) { 1112 | C.Mat_CompleteSymm(m.p, C.bool(lowerToUpper)) 1113 | } 1114 | 1115 | // ConvertScaleAbs scales, calculates absolute values, and converts the result to 8-bit. 1116 | // 1117 | // For further details, please see: 1118 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga3460e9c9f37b563ab9dd550c4d8c4e7d 1119 | // 1120 | func ConvertScaleAbs(src Mat, dst *Mat, alpha float64, beta float64) { 1121 | C.Mat_ConvertScaleAbs(src.p, dst.p, C.double(alpha), C.double(beta)) 1122 | } 1123 | 1124 | // CopyMakeBorder forms a border around an image (applies padding). 1125 | // 1126 | // For further details, please see: 1127 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga2ac1049c2c3dd25c2b41bffe17658a36 1128 | // 1129 | /* 1130 | func CopyMakeBorder(src Mat, dst *Mat, top int, bottom int, left int, right int, bt BorderType, value color.RGBA) { 1131 | 1132 | cValue := C.struct_Scalar{ 1133 | val1: C.double(value.B), 1134 | val2: C.double(value.G), 1135 | val3: C.double(value.R), 1136 | val4: C.double(value.A), 1137 | } 1138 | 1139 | C.Mat_CopyMakeBorder(src.p, dst.p, C.int(top), C.int(bottom), C.int(left), C.int(right), C.int(bt), cValue) 1140 | } 1141 | */ 1142 | 1143 | // DftFlags represents a DFT or DCT flag. 1144 | // 1145 | // For further details, please see: 1146 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaf4dde112b483b38175621befedda1f1c 1147 | // 1148 | type DftFlags int 1149 | 1150 | const ( 1151 | // DftForward performs forward 1D or 2D dft or dct. 1152 | DftForward DftFlags = 0 1153 | 1154 | // DftInverse performs an inverse 1D or 2D transform. 1155 | DftInverse DftFlags = 1 1156 | 1157 | // DftScale scales the result: divide it by the number of array elements. Normally, it is combined with DFT_INVERSE. 1158 | DftScale DftFlags = 2 1159 | 1160 | // DftRows performs a forward or inverse transform of every individual row of the input matrix. 1161 | DftRows DftFlags = 4 1162 | 1163 | // DftComplexOutput performs a forward transformation of 1D or 2D real array; the result, though being a complex array, has complex-conjugate symmetry 1164 | DftComplexOutput DftFlags = 16 1165 | 1166 | // DftRealOutput performs an inverse transformation of a 1D or 2D complex array; the result is normally a complex array of the same size, 1167 | // however, if the input array has conjugate-complex symmetry (for example, it is a result of forward transformation with DFT_COMPLEX_OUTPUT flag), 1168 | // the output is a real array. 1169 | DftRealOutput DftFlags = 32 1170 | 1171 | // DftComplexInput specifies that input is complex input. If this flag is set, the input must have 2 channels. 1172 | DftComplexInput DftFlags = 64 1173 | 1174 | // DctInverse performs an inverse 1D or 2D dct transform. 1175 | DctInverse = DftInverse 1176 | 1177 | // DctRows performs a forward or inverse dct transform of every individual row of the input matrix. 1178 | DctRows = DftRows 1179 | ) 1180 | 1181 | // DCT performs a forward or inverse discrete Cosine transform of 1D or 2D array. 1182 | // 1183 | // For further details, please see: 1184 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga85aad4d668c01fbd64825f589e3696d4 1185 | // 1186 | func DCT(src Mat, dst *Mat, flags DftFlags) { 1187 | C.Mat_DCT(src.p, dst.p, C.int(flags)) 1188 | } 1189 | 1190 | // Determinant returns the determinant of a square floating-point matrix. 1191 | // 1192 | // For further details, please see: 1193 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaf802bd9ca3e07b8b6170645ef0611d0c 1194 | // 1195 | func Determinant(src Mat) float64 { 1196 | return float64(C.Mat_Determinant(src.p)) 1197 | } 1198 | 1199 | // DFT performs a forward or inverse Discrete Fourier Transform (DFT) 1200 | // of a 1D or 2D floating-point array. 1201 | // 1202 | // For further details, please see: 1203 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d 1204 | // 1205 | func DFT(src Mat, dst *Mat, flags DftFlags) { 1206 | C.Mat_DFT(src.p, dst.p, C.int(flags)) 1207 | } 1208 | 1209 | // Divide performs the per-element division 1210 | // on two arrays or an array and a scalar. 1211 | // 1212 | // For further details, please see: 1213 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga6db555d30115642fedae0cda05604874 1214 | // 1215 | func Divide(src1 Mat, src2 Mat, dst *Mat) { 1216 | C.Mat_Divide(src1.p, src2.p, dst.p) 1217 | } 1218 | 1219 | // Eigen calculates eigenvalues and eigenvectors of a symmetric matrix. 1220 | // 1221 | // For further details, please see: 1222 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga9fa0d58657f60eaa6c71f6fbb40456e3 1223 | // 1224 | func Eigen(src Mat, eigenvalues *Mat, eigenvectors *Mat) bool { 1225 | ret := C.Mat_Eigen(src.p, eigenvalues.p, eigenvectors.p) 1226 | return bool(ret) 1227 | } 1228 | 1229 | // EigenNonSymmetric calculates eigenvalues and eigenvectors of a non-symmetric matrix (real eigenvalues only). 1230 | // 1231 | // For further details, please see: 1232 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaf51987e03cac8d171fbd2b327cf966f6 1233 | // 1234 | func EigenNonSymmetric(src Mat, eigenvalues *Mat, eigenvectors *Mat) { 1235 | C.Mat_EigenNonSymmetric(src.p, eigenvalues.p, eigenvectors.p) 1236 | } 1237 | 1238 | // Exp calculates the exponent of every array element. 1239 | // 1240 | // For further details, please see: 1241 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga3e10108e2162c338f1b848af619f39e5 1242 | // 1243 | func Exp(src Mat, dst *Mat) { 1244 | C.Mat_Exp(src.p, dst.p) 1245 | } 1246 | 1247 | // ExtractChannel extracts a single channel from src (coi is 0-based index). 1248 | // 1249 | // For further details, please see: 1250 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gacc6158574aa1f0281878c955bcf35642 1251 | // 1252 | func ExtractChannel(src Mat, dst *Mat, coi int) { 1253 | C.Mat_ExtractChannel(src.p, dst.p, C.int(coi)) 1254 | } 1255 | 1256 | // FindNonZero returns the list of locations of non-zero pixels. 1257 | // 1258 | // For further details, please see: 1259 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaed7df59a3539b4cc0fe5c9c8d7586190 1260 | // 1261 | func FindNonZero(src Mat, idx *Mat) { 1262 | C.Mat_FindNonZero(src.p, idx.p) 1263 | } 1264 | 1265 | // Flip flips a 2D array around horizontal(0), vertical(1), or both axes(-1). 1266 | // 1267 | // For further details, please see: 1268 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaca7be533e3dac7feb70fc60635adf441 1269 | // 1270 | func Flip(src Mat, dst *Mat, flipCode int) { 1271 | C.Mat_Flip(src.p, dst.p, C.int(flipCode)) 1272 | } 1273 | 1274 | // Gemm performs generalized matrix multiplication. 1275 | // 1276 | // For further details, please see: 1277 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gacb6e64071dffe36434e1e7ee79e7cb35 1278 | // 1279 | func Gemm(src1, src2 Mat, alpha float64, src3 Mat, beta float64, dst *Mat, flags int) { 1280 | C.Mat_Gemm(src1.p, src2.p, C.double(alpha), src3.p, C.double(beta), dst.p, C.int(flags)) 1281 | } 1282 | 1283 | // GetOptimalDFTSize returns the optimal Discrete Fourier Transform (DFT) size 1284 | // for a given vector size. 1285 | // 1286 | // For further details, please see: 1287 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299 1288 | // 1289 | func GetOptimalDFTSize(vecsize int) int { 1290 | return int(C.Mat_GetOptimalDFTSize(C.int(vecsize))) 1291 | } 1292 | 1293 | // Hconcat applies horizontal concatenation to given matrices. 1294 | // 1295 | // For further details, please see: 1296 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaab5ceee39e0580f879df645a872c6bf7 1297 | // 1298 | func Hconcat(src1, src2 Mat, dst *Mat) { 1299 | C.Mat_Hconcat(src1.p, src2.p, dst.p) 1300 | } 1301 | 1302 | // Vconcat applies vertical concatenation to given matrices. 1303 | // 1304 | // For further details, please see: 1305 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaab5ceee39e0580f879df645a872c6bf7 1306 | // 1307 | func Vconcat(src1, src2 Mat, dst *Mat) { 1308 | C.Mat_Vconcat(src1.p, src2.p, dst.p) 1309 | } 1310 | 1311 | // RotateFlag for image rotation 1312 | // 1313 | // 1314 | // For further details please see: 1315 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga6f45d55c0b1cc9d97f5353a7c8a7aac2 1316 | type RotateFlag int 1317 | 1318 | const ( 1319 | // Rotate90Clockwise allows to rotate image 90 degrees clockwise 1320 | Rotate90Clockwise RotateFlag = 0 1321 | // Rotate180Clockwise allows to rotate image 180 degrees clockwise 1322 | Rotate180Clockwise RotateFlag = 1 1323 | // Rotate90CounterClockwise allows to rotate 270 degrees clockwise 1324 | Rotate90CounterClockwise RotateFlag = 2 1325 | ) 1326 | 1327 | // Rotate rotates a 2D array in multiples of 90 degrees 1328 | // 1329 | // For further details, please see: 1330 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga4ad01c0978b0ce64baa246811deeac24 1331 | func Rotate(src Mat, dst *Mat, code RotateFlag) { 1332 | C.Rotate(src.p, dst.p, C.int(code)) 1333 | } 1334 | 1335 | // IDCT calculates the inverse Discrete Cosine Transform of a 1D or 2D array. 1336 | // 1337 | // For further details, please see: 1338 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga77b168d84e564c50228b69730a227ef2 1339 | // 1340 | func IDCT(src Mat, dst *Mat, flags int) { 1341 | C.Mat_Idct(src.p, dst.p, C.int(flags)) 1342 | } 1343 | 1344 | // IDFT calculates the inverse Discrete Fourier Transform of a 1D or 2D array. 1345 | // 1346 | // For further details, please see: 1347 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaa708aa2d2e57a508f968eb0f69aa5ff1 1348 | // 1349 | func IDFT(src Mat, dst *Mat, flags, nonzeroRows int) { 1350 | C.Mat_Idft(src.p, dst.p, C.int(flags), C.int(nonzeroRows)) 1351 | } 1352 | 1353 | // InRange checks if array elements lie between the elements of two Mat arrays. 1354 | // 1355 | // For further details, please see: 1356 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga48af0ab51e36436c5d04340e036ce981 1357 | // 1358 | func InRange(src, lb, ub Mat, dst *Mat) { 1359 | C.Mat_InRange(src.p, lb.p, ub.p, dst.p) 1360 | } 1361 | 1362 | // InRangeWithScalar checks if array elements lie between the elements of two Scalars 1363 | // 1364 | // For further details, please see: 1365 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga48af0ab51e36436c5d04340e036ce981 1366 | // 1367 | func InRangeWithScalar(src Mat, lb, ub Scalar, dst *Mat) { 1368 | lbVal := C.struct_Scalar{ 1369 | val1: C.double(lb.Val1), 1370 | val2: C.double(lb.Val2), 1371 | val3: C.double(lb.Val3), 1372 | val4: C.double(lb.Val4), 1373 | } 1374 | 1375 | ubVal := C.struct_Scalar{ 1376 | val1: C.double(ub.Val1), 1377 | val2: C.double(ub.Val2), 1378 | val3: C.double(ub.Val3), 1379 | val4: C.double(ub.Val4), 1380 | } 1381 | 1382 | C.Mat_InRangeWithScalar(src.p, lbVal, ubVal, dst.p) 1383 | } 1384 | 1385 | // InsertChannel inserts a single channel to dst (coi is 0-based index) 1386 | // (it replaces channel i with another in dst). 1387 | // 1388 | // For further details, please see: 1389 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga1d4bd886d35b00ec0b764cb4ce6eb515 1390 | // 1391 | func InsertChannel(src Mat, dst *Mat, coi int) { 1392 | C.Mat_InsertChannel(src.p, dst.p, C.int(coi)) 1393 | } 1394 | 1395 | // Invert finds the inverse or pseudo-inverse of a matrix. 1396 | // 1397 | // For further details, please see: 1398 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gad278044679d4ecf20f7622cc151aaaa2 1399 | // 1400 | func Invert(src Mat, dst *Mat, flags SolveDecompositionFlags) float64 { 1401 | ret := C.Mat_Invert(src.p, dst.p, C.int(flags)) 1402 | return float64(ret) 1403 | } 1404 | 1405 | // KMeansFlags for kmeans center selection 1406 | // 1407 | // For further details, please see: 1408 | // https://docs.opencv.org/master/d0/de1/group__core.html#ga276000efe55ee2756e0c471c7b270949 1409 | type KMeansFlags int 1410 | 1411 | const ( 1412 | // KMeansRandomCenters selects random initial centers in each attempt. 1413 | KMeansRandomCenters KMeansFlags = 0 1414 | // KMeansPPCenters uses kmeans++ center initialization by Arthur and Vassilvitskii [Arthur2007]. 1415 | KMeansPPCenters KMeansFlags = 1 1416 | // KMeansUseInitialLabels uses the user-supplied lables during the first (and possibly the only) attempt 1417 | // instead of computing them from the initial centers. For the second and further attempts, use the random or semi-random // centers. Use one of KMEANS_*_CENTERS flag to specify the exact method. 1418 | KMeansUseInitialLabels KMeansFlags = 2 1419 | ) 1420 | 1421 | // KMeans finds centers of clusters and groups input samples around the clusters. 1422 | // 1423 | // For further details, please see: 1424 | // https://docs.opencv.org/master/d5/d38/group__core__cluster.html#ga9a34dc06c6ec9460e90860f15bcd2f88 1425 | // 1426 | func KMeans(data Mat, k int, bestLabels *Mat, criteria TermCriteria, attempts int, flags KMeansFlags, centers *Mat) float64 { 1427 | ret := C.KMeans(data.p, C.int(k), bestLabels.p, criteria.p, C.int(attempts), C.int(flags), centers.p) 1428 | return float64(ret) 1429 | } 1430 | 1431 | // KMeansPoints finds centers of clusters and groups input samples around the clusters. 1432 | // 1433 | // For further details, please see: 1434 | // https://docs.opencv.org/master/d5/d38/group__core__cluster.html#ga9a34dc06c6ec9460e90860f15bcd2f88 1435 | // 1436 | func KMeansPoints(points PointVector, k int, bestLabels *Mat, criteria TermCriteria, attempts int, flags KMeansFlags, centers *Mat) float64 { 1437 | ret := C.KMeansPoints(points.p, C.int(k), bestLabels.p, criteria.p, C.int(attempts), C.int(flags), centers.p) 1438 | return float64(ret) 1439 | } 1440 | 1441 | // Log calculates the natural logarithm of every array element. 1442 | // 1443 | // For further details, please see: 1444 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga937ecdce4679a77168730830a955bea7 1445 | // 1446 | func Log(src Mat, dst *Mat) { 1447 | C.Mat_Log(src.p, dst.p) 1448 | } 1449 | 1450 | // Magnitude calculates the magnitude of 2D vectors. 1451 | // 1452 | // For further details, please see: 1453 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga6d3b097586bca4409873d64a90fe64c3 1454 | // 1455 | func Magnitude(x, y Mat, magnitude *Mat) { 1456 | C.Mat_Magnitude(x.p, y.p, magnitude.p) 1457 | } 1458 | 1459 | // Max calculates per-element maximum of two arrays or an array and a scalar. 1460 | // 1461 | // For further details, please see: 1462 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gacc40fa15eac0fb83f8ca70b7cc0b588d 1463 | // 1464 | func Max(src1, src2 Mat, dst *Mat) { 1465 | C.Mat_Max(src1.p, src2.p, dst.p) 1466 | } 1467 | 1468 | // MeanStdDev calculates a mean and standard deviation of array elements. 1469 | // 1470 | // For further details, please see: 1471 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga846c858f4004d59493d7c6a4354b301d 1472 | // 1473 | func MeanStdDev(src Mat, dst *Mat, dstStdDev *Mat) { 1474 | C.Mat_MeanStdDev(src.p, dst.p, dstStdDev.p) 1475 | } 1476 | 1477 | // Merge creates one multi-channel array out of several single-channel ones. 1478 | // 1479 | // For further details, please see: 1480 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga7d7b4d6c6ee504b30a20b1680029c7b4 1481 | // 1482 | func Merge(mv []Mat, dst *Mat) { 1483 | cMatArray := make([]C.Mat, len(mv)) 1484 | for i, r := range mv { 1485 | cMatArray[i] = r.p 1486 | } 1487 | cMats := C.struct_Mats{ 1488 | mats: (*C.Mat)(&cMatArray[0]), 1489 | length: C.int(len(mv)), 1490 | } 1491 | 1492 | C.Mat_Merge(cMats, dst.p) 1493 | } 1494 | 1495 | // Min calculates per-element minimum of two arrays or an array and a scalar. 1496 | // 1497 | // For further details, please see: 1498 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga9af368f182ee76d0463d0d8d5330b764 1499 | // 1500 | func Min(src1, src2 Mat, dst *Mat) { 1501 | C.Mat_Min(src1.p, src2.p, dst.p) 1502 | } 1503 | 1504 | // MinMaxIdx finds the global minimum and maximum in an array. 1505 | // 1506 | // For further details, please see: 1507 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga7622c466c628a75d9ed008b42250a73f 1508 | // 1509 | func MinMaxIdx(input Mat) (minVal, maxVal float32, minIdx, maxIdx int) { 1510 | var cMinVal C.double 1511 | var cMaxVal C.double 1512 | var cMinIdx C.int 1513 | var cMaxIdx C.int 1514 | 1515 | C.Mat_MinMaxIdx(input.p, &cMinVal, &cMaxVal, &cMinIdx, &cMaxIdx) 1516 | 1517 | return float32(cMinVal), float32(cMaxVal), int(minIdx), int(maxIdx) 1518 | } 1519 | 1520 | // MinMaxLoc finds the global minimum and maximum in an array. 1521 | // 1522 | // For further details, please see: 1523 | // https://docs.opencv.org/trunk/d2/de8/group__core__array.html#gab473bf2eb6d14ff97e89b355dac20707 1524 | // 1525 | func MinMaxLoc(input Mat) (minVal, maxVal float32, minLoc, maxLoc image.Point) { 1526 | var cMinVal C.double 1527 | var cMaxVal C.double 1528 | var cMinLoc C.struct_Point 1529 | var cMaxLoc C.struct_Point 1530 | 1531 | C.Mat_MinMaxLoc(input.p, &cMinVal, &cMaxVal, &cMinLoc, &cMaxLoc) 1532 | 1533 | minLoc = image.Pt(int(cMinLoc.x), int(cMinLoc.y)) 1534 | maxLoc = image.Pt(int(cMaxLoc.x), int(cMaxLoc.y)) 1535 | 1536 | return float32(cMinVal), float32(cMaxVal), minLoc, maxLoc 1537 | } 1538 | 1539 | // Copies specified channels from input arrays to the specified channels of output arrays. 1540 | // 1541 | // For further details, please see: 1542 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga51d768c270a1cdd3497255017c4504be 1543 | // 1544 | func MixChannels(src []Mat, dst []Mat, fromTo []int) { 1545 | cSrcArray := make([]C.Mat, len(src)) 1546 | for i, r := range src { 1547 | cSrcArray[i] = r.p 1548 | } 1549 | cSrcMats := C.struct_Mats{ 1550 | mats: (*C.Mat)(&cSrcArray[0]), 1551 | length: C.int(len(src)), 1552 | } 1553 | 1554 | cDstArray := make([]C.Mat, len(dst)) 1555 | for i, r := range dst { 1556 | cDstArray[i] = r.p 1557 | } 1558 | cDstMats := C.struct_Mats{ 1559 | mats: (*C.Mat)(&cDstArray[0]), 1560 | length: C.int(len(dst)), 1561 | } 1562 | 1563 | cFromToArray := make([]C.int, len(fromTo)) 1564 | for i, ft := range fromTo { 1565 | cFromToArray[i] = C.int(ft) 1566 | } 1567 | 1568 | cFromToIntVector := C.IntVector{ 1569 | val: (*C.int)(&cFromToArray[0]), 1570 | length: C.int(len(fromTo)), 1571 | } 1572 | 1573 | C.Mat_MixChannels(cSrcMats, cDstMats, cFromToIntVector) 1574 | 1575 | for i := C.int(0); i < cDstMats.length; i++ { 1576 | dst[i].p = C.Mats_get(cDstMats, i) 1577 | } 1578 | } 1579 | 1580 | //Mulspectrums performs the per-element multiplication of two Fourier spectrums. 1581 | // 1582 | // For further details, please see: 1583 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga3ab38646463c59bf0ce962a9d51db64f 1584 | // 1585 | func MulSpectrums(a Mat, b Mat, dst *Mat, flags DftFlags) { 1586 | C.Mat_MulSpectrums(a.p, b.p, dst.p, C.int(flags)) 1587 | } 1588 | 1589 | // Multiply calculates the per-element scaled product of two arrays. 1590 | // Both input arrays must be of the same size and the same type. 1591 | // 1592 | // For further details, please see: 1593 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga979d898a58d7f61c53003e162e7ad89f 1594 | // 1595 | func Multiply(src1 Mat, src2 Mat, dst *Mat) { 1596 | C.Mat_Multiply(src1.p, src2.p, dst.p) 1597 | } 1598 | 1599 | // MultiplyWithParams calculates the per-element scaled product of two arrays. 1600 | // Both input arrays must be of the same size and the same type. 1601 | // 1602 | // For further details, please see: 1603 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga979d898a58d7f61c53003e162e7ad89f 1604 | // 1605 | func MultiplyWithParams(src1 Mat, src2 Mat, dst *Mat, scale float64, dtype MatType) { 1606 | C.Mat_MultiplyWithParams(src1.p, src2.p, dst.p, C.double(scale), C.int(dtype)) 1607 | } 1608 | 1609 | // NormType for normalization operations. 1610 | // 1611 | // For further details, please see: 1612 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gad12cefbcb5291cf958a85b4b67b6149f 1613 | // 1614 | type NormType int 1615 | 1616 | const ( 1617 | // NormInf indicates use infinite normalization. 1618 | NormInf NormType = 1 1619 | 1620 | // NormL1 indicates use L1 normalization. 1621 | NormL1 NormType = 2 1622 | 1623 | // NormL2 indicates use L2 normalization. 1624 | NormL2 NormType = 4 1625 | 1626 | // NormL2Sqr indicates use L2 squared normalization. 1627 | NormL2Sqr NormType = 5 1628 | 1629 | // NormHamming indicates use Hamming normalization. 1630 | NormHamming NormType = 6 1631 | 1632 | // NormHamming2 indicates use Hamming 2-bit normalization. 1633 | NormHamming2 NormType = 7 1634 | 1635 | // NormTypeMask indicates use type mask for normalization. 1636 | NormTypeMask NormType = 7 1637 | 1638 | // NormRelative indicates use relative normalization. 1639 | NormRelative NormType = 8 1640 | 1641 | // NormMinMax indicates use min/max normalization. 1642 | NormMinMax NormType = 32 1643 | ) 1644 | 1645 | // Normalize normalizes the norm or value range of an array. 1646 | // 1647 | // For further details, please see: 1648 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga87eef7ee3970f86906d69a92cbf064bd 1649 | // 1650 | func Normalize(src Mat, dst *Mat, alpha float64, beta float64, typ NormType) { 1651 | C.Mat_Normalize(src.p, dst.p, C.double(alpha), C.double(beta), C.int(typ)) 1652 | } 1653 | 1654 | // Norm calculates the absolute norm of an array. 1655 | // 1656 | // For further details, please see: 1657 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga7c331fb8dd951707e184ef4e3f21dd33 1658 | // 1659 | func Norm(src1 Mat, normType NormType) float64 { 1660 | return float64(C.Norm(src1.p, C.int(normType))) 1661 | } 1662 | 1663 | // Norm calculates the absolute difference/relative norm of two arrays. 1664 | // 1665 | // For further details, please see: 1666 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga7c331fb8dd951707e184ef4e3f21dd33 1667 | // 1668 | func NormWithMats(src1 Mat, src2 Mat, normType NormType) float64 { 1669 | return float64(C.NormWithMats(src1.p, src2.p, C.int(normType))) 1670 | } 1671 | 1672 | // PerspectiveTransform performs the perspective matrix transformation of vectors. 1673 | // 1674 | // For further details, please see: 1675 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gad327659ac03e5fd6894b90025e6900a7 1676 | // 1677 | func PerspectiveTransform(src Mat, dst *Mat, tm Mat) { 1678 | C.Mat_PerspectiveTransform(src.p, dst.p, tm.p) 1679 | } 1680 | 1681 | // TermCriteriaType for TermCriteria. 1682 | // 1683 | // For further details, please see: 1684 | // https://docs.opencv.org/master/d9/d5d/classcv_1_1TermCriteria.html#a56fecdc291ccaba8aad27d67ccf72c57 1685 | // 1686 | type TermCriteriaType int 1687 | 1688 | const ( 1689 | // Count is the maximum number of iterations or elements to compute. 1690 | Count TermCriteriaType = 1 1691 | 1692 | // MaxIter is the maximum number of iterations or elements to compute. 1693 | MaxIter TermCriteriaType = 1 1694 | 1695 | // EPS is the desired accuracy or change in parameters at which the 1696 | // iterative algorithm stops. 1697 | EPS TermCriteriaType = 2 1698 | ) 1699 | 1700 | type SolveDecompositionFlags int 1701 | 1702 | const ( 1703 | // Gaussian elimination with the optimal pivot element chosen. 1704 | SolveDecompositionLu SolveDecompositionFlags = 0 1705 | 1706 | // Singular value decomposition (SVD) method. The system can be over-defined and/or the matrix src1 can be singular. 1707 | SolveDecompositionSvd SolveDecompositionFlags = 1 1708 | 1709 | // Eigenvalue decomposition. The matrix src1 must be symmetrical. 1710 | SolveDecompositionEing SolveDecompositionFlags = 2 1711 | 1712 | // Cholesky LL^T factorization. The matrix src1 must be symmetrical and positively defined. 1713 | SolveDecompositionCholesky SolveDecompositionFlags = 3 1714 | 1715 | // QR factorization. The system can be over-defined and/or the matrix src1 can be singular. 1716 | SolveDecompositionQr SolveDecompositionFlags = 4 1717 | 1718 | // While all the previous flags are mutually exclusive, this flag can be used together with any of the previous. 1719 | // It means that the normal equations 𝚜𝚛𝚌𝟷^T⋅𝚜𝚛𝚌𝟷⋅𝚍𝚜𝚝=𝚜𝚛𝚌𝟷^T𝚜𝚛𝚌𝟸 are solved instead of the original system 1720 | // 𝚜𝚛𝚌𝟷⋅𝚍𝚜𝚝=𝚜𝚛𝚌𝟸. 1721 | SolveDecompositionNormal SolveDecompositionFlags = 5 1722 | ) 1723 | 1724 | // Solve solves one or more linear systems or least-squares problems. 1725 | // 1726 | // For further details, please see: 1727 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga12b43690dbd31fed96f213eefead2373 1728 | // 1729 | func Solve(src1 Mat, src2 Mat, dst *Mat, flags SolveDecompositionFlags) bool { 1730 | return bool(C.Mat_Solve(src1.p, src2.p, dst.p, C.int(flags))) 1731 | } 1732 | 1733 | // SolveCubic finds the real roots of a cubic equation. 1734 | // 1735 | // For further details, please see: 1736 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga1c3b0b925b085b6e96931ee309e6a1da 1737 | // 1738 | func SolveCubic(coeffs Mat, roots *Mat) int { 1739 | return int(C.Mat_SolveCubic(coeffs.p, roots.p)) 1740 | } 1741 | 1742 | // SolvePoly finds the real or complex roots of a polynomial equation. 1743 | // 1744 | // For further details, please see: 1745 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gac2f5e953016fabcdf793d762f4ec5dce 1746 | // 1747 | func SolvePoly(coeffs Mat, roots *Mat, maxIters int) float64 { 1748 | return float64(C.Mat_SolvePoly(coeffs.p, roots.p, C.int(maxIters))) 1749 | } 1750 | 1751 | type ReduceTypes int 1752 | 1753 | const ( 1754 | // The output is the sum of all rows/columns of the matrix. 1755 | ReduceSum ReduceTypes = 0 1756 | 1757 | // The output is the mean vector of all rows/columns of the matrix. 1758 | ReduceAvg ReduceTypes = 1 1759 | 1760 | // The output is the maximum (column/row-wise) of all rows/columns of the matrix. 1761 | ReduceMax ReduceTypes = 2 1762 | 1763 | // The output is the minimum (column/row-wise) of all rows/columns of the matrix. 1764 | ReduceMin ReduceTypes = 3 1765 | ) 1766 | 1767 | // Reduce reduces a matrix to a vector. 1768 | // 1769 | // For further details, please see: 1770 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga4b78072a303f29d9031d56e5638da78e 1771 | // 1772 | func Reduce(src Mat, dst *Mat, dim int, rType ReduceTypes, dType MatType) { 1773 | C.Mat_Reduce(src.p, dst.p, C.int(dim), C.int(rType), C.int(dType)) 1774 | } 1775 | 1776 | // Repeat fills the output array with repeated copies of the input array. 1777 | // 1778 | // For further details, please see: 1779 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga496c3860f3ac44c40b48811333cfda2d 1780 | // 1781 | func Repeat(src Mat, nY int, nX int, dst *Mat) { 1782 | C.Mat_Repeat(src.p, C.int(nY), C.int(nX), dst.p) 1783 | } 1784 | 1785 | // Calculates the sum of a scaled array and another array. 1786 | // 1787 | // For further details, please see: 1788 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga9e0845db4135f55dcf20227402f00d98 1789 | // 1790 | func ScaleAdd(src1 Mat, alpha float64, src2 Mat, dst *Mat) { 1791 | C.Mat_ScaleAdd(src1.p, C.double(alpha), src2.p, dst.p) 1792 | } 1793 | 1794 | // SetIdentity initializes a scaled identity matrix. 1795 | // For further details, please see: 1796 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga388d7575224a4a277ceb98ccaa327c99 1797 | // 1798 | func SetIdentity(src Mat, scalar float64) { 1799 | C.Mat_SetIdentity(src.p, C.double(scalar)) 1800 | } 1801 | 1802 | type SortFlags int 1803 | 1804 | const ( 1805 | // Each matrix row is sorted independently 1806 | SortEveryRow SortFlags = 0 1807 | 1808 | // Each matrix column is sorted independently; this flag and the previous one are mutually exclusive. 1809 | SortEveryColumn SortFlags = 1 1810 | 1811 | // Each matrix row is sorted in the ascending order. 1812 | SortAscending SortFlags = 0 1813 | 1814 | // Each matrix row is sorted in the descending order; this flag and the previous one are also mutually exclusive. 1815 | SortDescending SortFlags = 16 1816 | ) 1817 | 1818 | // Sort sorts each row or each column of a matrix. 1819 | // 1820 | // For further details, please see: 1821 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga45dd56da289494ce874be2324856898f 1822 | // 1823 | func Sort(src Mat, dst *Mat, flags SortFlags) { 1824 | C.Mat_Sort(src.p, dst.p, C.int(flags)) 1825 | } 1826 | 1827 | // SortIdx sorts each row or each column of a matrix. 1828 | // Instead of reordering the elements themselves, it stores the indices of sorted elements in the output array 1829 | // 1830 | // For further details, please see: 1831 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gadf35157cbf97f3cb85a545380e383506 1832 | // 1833 | func SortIdx(src Mat, dst *Mat, flags SortFlags) { 1834 | C.Mat_SortIdx(src.p, dst.p, C.int(flags)) 1835 | } 1836 | 1837 | // Split creates an array of single channel images from a multi-channel image 1838 | // Created images should be closed manualy to avoid memory leaks. 1839 | // 1840 | // For further details, please see: 1841 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga0547c7fed86152d7e9d0096029c8518a 1842 | // 1843 | func Split(src Mat) (mv []Mat) { 1844 | cMats := C.struct_Mats{} 1845 | C.Mat_Split(src.p, &(cMats)) 1846 | defer C.Mats_Close(cMats) 1847 | mv = make([]Mat, cMats.length) 1848 | for i := C.int(0); i < cMats.length; i++ { 1849 | mv[i].p = C.Mats_get(cMats, i) 1850 | addMatToProfile(mv[i].p) 1851 | } 1852 | return 1853 | } 1854 | 1855 | // Subtract calculates the per-element subtraction of two arrays or an array and a scalar. 1856 | // 1857 | // For further details, please see: 1858 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaa0f00d98b4b5edeaeb7b8333b2de353b 1859 | // 1860 | func Subtract(src1 Mat, src2 Mat, dst *Mat) { 1861 | C.Mat_Subtract(src1.p, src2.p, dst.p) 1862 | } 1863 | 1864 | // Trace returns the trace of a matrix. 1865 | // 1866 | // For further details, please see: 1867 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga3419ac19c7dcd2be4bd552a23e147dd8 1868 | // 1869 | func Trace(src Mat) Scalar { 1870 | s := C.Mat_Trace(src.p) 1871 | return NewScalar(float64(s.val1), float64(s.val2), float64(s.val3), float64(s.val4)) 1872 | } 1873 | 1874 | // Transform performs the matrix transformation of every array element. 1875 | // 1876 | // For further details, please see: 1877 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga393164aa54bb9169ce0a8cc44e08ff22 1878 | // 1879 | func Transform(src Mat, dst *Mat, tm Mat) { 1880 | C.Mat_Transform(src.p, dst.p, tm.p) 1881 | } 1882 | 1883 | // Transpose transposes a matrix. 1884 | // 1885 | // For further details, please see: 1886 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga46630ed6c0ea6254a35f447289bd7404 1887 | // 1888 | func Transpose(src Mat, dst *Mat) { 1889 | C.Mat_Transpose(src.p, dst.p) 1890 | } 1891 | 1892 | // Pow raises every array element to a power. 1893 | // 1894 | // For further details, please see: 1895 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaf0d056b5bd1dc92500d6f6cf6bac41ef 1896 | // 1897 | func Pow(src Mat, power float64, dst *Mat) { 1898 | C.Mat_Pow(src.p, C.double(power), dst.p) 1899 | } 1900 | 1901 | // PolatToCart calculates x and y coordinates of 2D vectors from their magnitude and angle. 1902 | // 1903 | // For further details, please see: 1904 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga581ff9d44201de2dd1b40a50db93d665 1905 | // 1906 | func PolarToCart(magnitude Mat, degree Mat, x *Mat, y *Mat, angleInDegrees bool) { 1907 | C.Mat_PolarToCart(magnitude.p, degree.p, x.p, y.p, C.bool(angleInDegrees)) 1908 | } 1909 | 1910 | // Phase calculates the rotation angle of 2D vectors. 1911 | // 1912 | // For further details, please see: 1913 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga9db9ca9b4d81c3bde5677b8f64dc0137 1914 | // 1915 | func Phase(x, y Mat, angle *Mat, angleInDegrees bool) { 1916 | C.Mat_Phase(x.p, y.p, angle.p, C.bool(angleInDegrees)) 1917 | } 1918 | 1919 | // TermCriteria is the criteria for iterative algorithms. 1920 | // 1921 | // For further details, please see: 1922 | // https://docs.opencv.org/master/d9/d5d/classcv_1_1TermCriteria.html 1923 | // 1924 | type TermCriteria struct { 1925 | p C.TermCriteria 1926 | } 1927 | 1928 | // NewTermCriteria returns a new TermCriteria. 1929 | func NewTermCriteria(typ TermCriteriaType, maxCount int, epsilon float64) TermCriteria { 1930 | return TermCriteria{p: C.TermCriteria_New(C.int(typ), C.int(maxCount), C.double(epsilon))} 1931 | } 1932 | 1933 | // Scalar is a 4-element vector widely used in OpenCV to pass pixel values. 1934 | // 1935 | // For further details, please see: 1936 | // http://docs.opencv.org/master/d1/da0/classcv_1_1Scalar__.html 1937 | // 1938 | type Scalar struct { 1939 | Val1 float64 1940 | Val2 float64 1941 | Val3 float64 1942 | Val4 float64 1943 | } 1944 | 1945 | // NewScalar returns a new Scalar. These are usually colors typically being in BGR order. 1946 | func NewScalar(v1 float64, v2 float64, v3 float64, v4 float64) Scalar { 1947 | s := Scalar{Val1: v1, Val2: v2, Val3: v3, Val4: v4} 1948 | return s 1949 | } 1950 | 1951 | // KeyPoint is data structure for salient point detectors. 1952 | // 1953 | // For further details, please see: 1954 | // https://docs.opencv.org/master/d2/d29/classcv_1_1KeyPoint.html 1955 | // 1956 | type KeyPoint struct { 1957 | X, Y float64 1958 | Size, Angle, Response float64 1959 | Octave, ClassID int 1960 | } 1961 | 1962 | // DMatch is data structure for matching keypoint descriptors. 1963 | // 1964 | // For further details, please see: 1965 | // https://docs.opencv.org/master/d4/de0/classcv_1_1DMatch.html#a546ddb9a87898f06e510e015a6de596e 1966 | // 1967 | type DMatch struct { 1968 | QueryIdx int 1969 | TrainIdx int 1970 | ImgIdx int 1971 | Distance float64 1972 | } 1973 | 1974 | // Vecb is a generic vector of bytes. 1975 | type Vecb []uint8 1976 | 1977 | // GetVecbAt returns a vector of bytes. Its size corresponds to the number 1978 | // of channels of the Mat. 1979 | func (m *Mat) GetVecbAt(row int, col int) Vecb { 1980 | ch := m.Channels() 1981 | v := make(Vecb, ch) 1982 | 1983 | for c := 0; c < ch; c++ { 1984 | v[c] = m.GetUCharAt(row, col*ch+c) 1985 | } 1986 | 1987 | return v 1988 | } 1989 | 1990 | // Vecf is a generic vector of floats. 1991 | type Vecf []float32 1992 | 1993 | // GetVecfAt returns a vector of floats. Its size corresponds to the number of 1994 | // channels of the Mat. 1995 | func (m *Mat) GetVecfAt(row int, col int) Vecf { 1996 | ch := m.Channels() 1997 | v := make(Vecf, ch) 1998 | 1999 | for c := 0; c < ch; c++ { 2000 | v[c] = m.GetFloatAt(row, col*ch+c) 2001 | } 2002 | 2003 | return v 2004 | } 2005 | 2006 | // Vecd is a generic vector of float64/doubles. 2007 | type Vecd []float64 2008 | 2009 | // GetVecdAt returns a vector of float64s. Its size corresponds to the number 2010 | // of channels of the Mat. 2011 | func (m *Mat) GetVecdAt(row int, col int) Vecd { 2012 | ch := m.Channels() 2013 | v := make(Vecd, ch) 2014 | 2015 | for c := 0; c < ch; c++ { 2016 | v[c] = m.GetDoubleAt(row, col*ch+c) 2017 | } 2018 | 2019 | return v 2020 | } 2021 | 2022 | // Veci is a generic vector of integers. 2023 | type Veci []int32 2024 | 2025 | // GetVeciAt returns a vector of integers. Its size corresponds to the number 2026 | // of channels of the Mat. 2027 | func (m *Mat) GetVeciAt(row int, col int) Veci { 2028 | ch := m.Channels() 2029 | v := make(Veci, ch) 2030 | 2031 | for c := 0; c < ch; c++ { 2032 | v[c] = m.GetIntAt(row, col*ch+c) 2033 | } 2034 | 2035 | return v 2036 | } 2037 | 2038 | // PointVector is a wrapper around a std::vector< cv::Point >* 2039 | // This is needed anytime that you need to pass or receive a collection of points. 2040 | type PointVector struct { 2041 | p C.PointVector 2042 | } 2043 | 2044 | // NewPointVector returns a new empty PointVector. 2045 | func NewPointVector() PointVector { 2046 | return PointVector{p: C.PointVector_New()} 2047 | } 2048 | 2049 | // NewPointVectorFromPoints returns a new PointVector that has been 2050 | // initialized to a slice of image.Point. 2051 | func NewPointVectorFromPoints(pts []image.Point) PointVector { 2052 | p := (*C.struct_Point)(C.malloc(C.size_t(C.sizeof_struct_Point * len(pts)))) 2053 | defer C.free(unsafe.Pointer(p)) 2054 | 2055 | h := &reflect.SliceHeader{ 2056 | Data: uintptr(unsafe.Pointer(p)), 2057 | Len: len(pts), 2058 | Cap: len(pts), 2059 | } 2060 | pa := *(*[]C.Point)(unsafe.Pointer(h)) 2061 | 2062 | for j, point := range pts { 2063 | pa[j] = C.struct_Point{ 2064 | x: C.int(point.X), 2065 | y: C.int(point.Y), 2066 | } 2067 | } 2068 | 2069 | cpoints := C.struct_Points{ 2070 | points: (*C.Point)(p), 2071 | length: C.int(len(pts)), 2072 | } 2073 | 2074 | return PointVector{p: C.PointVector_NewFromPoints(cpoints)} 2075 | } 2076 | 2077 | // NewPointVectorFromMat returns a new PointVector that has been 2078 | // wrapped around a Mat of type CV_32SC2 with a single columm. 2079 | func NewPointVectorFromMat(mat Mat) PointVector { 2080 | return PointVector{p: C.PointVector_NewFromMat(mat.p)} 2081 | } 2082 | 2083 | // IsNil checks the CGo pointer in the PointVector. 2084 | func (pv PointVector) IsNil() bool { 2085 | return pv.p == nil 2086 | } 2087 | 2088 | // Size returns how many Point are in the PointVector. 2089 | func (pv PointVector) Size() int { 2090 | return int(C.PointVector_Size(pv.p)) 2091 | } 2092 | 2093 | // At returns the image.Point 2094 | func (pv PointVector) At(idx int) image.Point { 2095 | if idx > pv.Size() { 2096 | return image.Point{} 2097 | } 2098 | 2099 | cp := C.PointVector_At(pv.p, C.int(idx)) 2100 | return image.Pt(int(cp.x), int(cp.y)) 2101 | } 2102 | 2103 | // Append appends an image.Point at end of the PointVector. 2104 | func (pv PointVector) Append(point image.Point) { 2105 | p := C.struct_Point{ 2106 | x: C.int(point.X), 2107 | y: C.int(point.Y), 2108 | } 2109 | 2110 | C.PointVector_Append(pv.p, p) 2111 | 2112 | return 2113 | } 2114 | 2115 | // ToPoints returns a slice of image.Point for the data in this PointVector. 2116 | func (pv PointVector) ToPoints() []image.Point { 2117 | points := make([]image.Point, pv.Size()) 2118 | 2119 | for j := 0; j < pv.Size(); j++ { 2120 | points[j] = pv.At(j) 2121 | } 2122 | return points 2123 | } 2124 | 2125 | // Close closes and frees memory for this PointVector. 2126 | func (pv PointVector) Close() { 2127 | C.PointVector_Close(pv.p) 2128 | } 2129 | 2130 | // PointsVector is a wrapper around a std::vector< std::vector< cv::Point > >* 2131 | type PointsVector struct { 2132 | p C.PointsVector 2133 | } 2134 | 2135 | // NewPointsVector returns a new empty PointsVector. 2136 | func NewPointsVector() PointsVector { 2137 | return PointsVector{p: C.PointsVector_New()} 2138 | } 2139 | 2140 | // NewPointsVectorFromPoints returns a new PointsVector that has been 2141 | // initialized to a slice of slices of image.Point. 2142 | func NewPointsVectorFromPoints(pts [][]image.Point) PointsVector { 2143 | points := make([]C.struct_Points, len(pts)) 2144 | 2145 | for i, pt := range pts { 2146 | p := (*C.struct_Point)(C.malloc(C.size_t(C.sizeof_struct_Point * len(pt)))) 2147 | defer C.free(unsafe.Pointer(p)) 2148 | 2149 | h := &reflect.SliceHeader{ 2150 | Data: uintptr(unsafe.Pointer(p)), 2151 | Len: len(pt), 2152 | Cap: len(pt), 2153 | } 2154 | pa := *(*[]C.Point)(unsafe.Pointer(h)) 2155 | 2156 | for j, point := range pt { 2157 | pa[j] = C.struct_Point{ 2158 | x: C.int(point.X), 2159 | y: C.int(point.Y), 2160 | } 2161 | } 2162 | 2163 | points[i] = C.struct_Points{ 2164 | points: (*C.Point)(p), 2165 | length: C.int(len(pt)), 2166 | } 2167 | } 2168 | 2169 | cPoints := C.struct_Contours{ 2170 | contours: (*C.struct_Points)(&points[0]), 2171 | length: C.int(len(pts)), 2172 | } 2173 | 2174 | return PointsVector{p: C.PointsVector_NewFromPoints(cPoints)} 2175 | } 2176 | 2177 | func (pvs PointsVector) P() C.PointsVector { 2178 | return pvs.p 2179 | } 2180 | 2181 | // ToPoints returns a slice of slices of image.Point for the data in this PointsVector. 2182 | func (pvs PointsVector) ToPoints() [][]image.Point { 2183 | ppoints := make([][]image.Point, pvs.Size()) 2184 | for i := 0; i < pvs.Size(); i++ { 2185 | pts := pvs.At(i) 2186 | points := make([]image.Point, pts.Size()) 2187 | 2188 | for j := 0; j < pts.Size(); j++ { 2189 | points[j] = pts.At(j) 2190 | } 2191 | ppoints[i] = points 2192 | } 2193 | 2194 | return ppoints 2195 | } 2196 | 2197 | // IsNil checks the CGo pointer in the PointsVector. 2198 | func (pvs PointsVector) IsNil() bool { 2199 | return pvs.p == nil 2200 | } 2201 | 2202 | // Size returns how many vectors of Points are in the PointsVector. 2203 | func (pvs PointsVector) Size() int { 2204 | return int(C.PointsVector_Size(pvs.p)) 2205 | } 2206 | 2207 | // At returns the PointVector at that index of the PointsVector. 2208 | func (pvs PointsVector) At(idx int) PointVector { 2209 | if idx > pvs.Size() { 2210 | return PointVector{} 2211 | } 2212 | 2213 | return PointVector{p: C.PointsVector_At(pvs.p, C.int(idx))} 2214 | } 2215 | 2216 | // Append appends a PointVector at end of the PointsVector. 2217 | func (pvs PointsVector) Append(pv PointVector) { 2218 | if !pv.IsNil() { 2219 | C.PointsVector_Append(pvs.p, pv.p) 2220 | } 2221 | 2222 | return 2223 | } 2224 | 2225 | // Close closes and frees memory for this PointsVector. 2226 | func (pvs PointsVector) Close() { 2227 | C.PointsVector_Close(pvs.p) 2228 | } 2229 | 2230 | // Point2fVector is a wrapper around a std::vector< cv::Point2f >* 2231 | // This is needed anytime that you need to pass or receive a collection of points. 2232 | type Point2fVector struct { 2233 | p C.Point2fVector 2234 | } 2235 | 2236 | // NewPoint2fVector returns a new empty Point2fVector. 2237 | func NewPoint2fVector() Point2fVector { 2238 | return Point2fVector{p: C.Point2fVector_New()} 2239 | } 2240 | 2241 | // NewPoint2fVectorFromPoints returns a new Point2fVector that has been 2242 | // initialized to a slice of image.Point. 2243 | func NewPoint2fVectorFromPoints(pts []Point2f) Point2fVector { 2244 | p := (*C.struct_Point2f)(C.malloc(C.size_t(C.sizeof_struct_Point2f * len(pts)))) 2245 | defer C.free(unsafe.Pointer(p)) 2246 | 2247 | h := &reflect.SliceHeader{ 2248 | Data: uintptr(unsafe.Pointer(p)), 2249 | Len: len(pts), 2250 | Cap: len(pts), 2251 | } 2252 | pa := *(*[]C.Point2f)(unsafe.Pointer(h)) 2253 | 2254 | for j, point := range pts { 2255 | pa[j] = C.struct_Point2f{ 2256 | x: C.float(point.X), 2257 | y: C.float(point.Y), 2258 | } 2259 | } 2260 | 2261 | cpoints := C.struct_Points2f{ 2262 | points: (*C.Point2f)(p), 2263 | length: C.int(len(pts)), 2264 | } 2265 | 2266 | return Point2fVector{p: C.Point2fVector_NewFromPoints(cpoints)} 2267 | } 2268 | 2269 | // NewPoint2fVectorFromMat returns a new Point2fVector that has been 2270 | // wrapped around a Mat of type CV_32FC2 with a single columm. 2271 | func NewPoint2fVectorFromMat(mat Mat) Point2fVector { 2272 | return Point2fVector{p: C.Point2fVector_NewFromMat(mat.p)} 2273 | } 2274 | 2275 | // IsNil checks the CGo pointer in the Point2fVector. 2276 | func (pfv Point2fVector) IsNil() bool { 2277 | return pfv.p == nil 2278 | } 2279 | 2280 | // Size returns how many Point are in the PointVector. 2281 | func (pfv Point2fVector) Size() int { 2282 | return int(C.Point2fVector_Size(pfv.p)) 2283 | } 2284 | 2285 | // At returns the image.Point 2286 | func (pfv Point2fVector) At(idx int) Point2f { 2287 | if idx > pfv.Size() { 2288 | return Point2f{} 2289 | } 2290 | 2291 | cp := C.Point2fVector_At(pfv.p, C.int(idx)) 2292 | return Point2f{float32(cp.x), float32(cp.y)} 2293 | } 2294 | 2295 | // ToPoints returns a slice of image.Point for the data in this PointVector. 2296 | func (pfv Point2fVector) ToPoints() []Point2f { 2297 | points := make([]Point2f, pfv.Size()) 2298 | 2299 | for j := 0; j < pfv.Size(); j++ { 2300 | points[j] = pfv.At(j) 2301 | } 2302 | return points 2303 | } 2304 | 2305 | // Close closes and frees memory for this Point2fVector. 2306 | func (pfv Point2fVector) Close() { 2307 | C.Point2fVector_Close(pfv.p) 2308 | } 2309 | 2310 | // GetTickCount returns the number of ticks. 2311 | // 2312 | // For further details, please see: 2313 | // https://docs.opencv.org/master/db/de0/group__core__utils.html#gae73f58000611a1af25dd36d496bf4487 2314 | // 2315 | func GetTickCount() float64 { 2316 | return float64(C.GetCVTickCount()) 2317 | } 2318 | 2319 | // GetTickFrequency returns the number of ticks per second. 2320 | // 2321 | // For further details, please see: 2322 | // https://docs.opencv.org/master/db/de0/group__core__utils.html#ga705441a9ef01f47acdc55d87fbe5090c 2323 | // 2324 | func GetTickFrequency() float64 { 2325 | return float64(C.GetTickFrequency()) 2326 | } 2327 | 2328 | func toByteArray(b []byte) (*C.struct_ByteArray, error) { 2329 | if len(b) == 0 { 2330 | return nil, ErrEmptyByteSlice 2331 | } 2332 | return &C.struct_ByteArray{ 2333 | data: (*C.char)(unsafe.Pointer(&b[0])), 2334 | length: C.int(len(b)), 2335 | }, nil 2336 | } 2337 | 2338 | func toGoBytes(b C.struct_ByteArray) []byte { 2339 | return C.GoBytes(unsafe.Pointer(b.data), b.length) 2340 | } 2341 | 2342 | // Converts CStrings to a slice of Go strings even when the C strings are not contiguous in memory 2343 | func toGoStrings(strs C.CStrings) []string { 2344 | length := int(strs.length) 2345 | tmpslice := (*[1 << 20]*C.char)(unsafe.Pointer(strs.strs))[:length:length] 2346 | gostrings := make([]string, length) 2347 | for i, s := range tmpslice { 2348 | gostrings[i] = C.GoString(s) 2349 | } 2350 | return gostrings 2351 | } 2352 | 2353 | func toRectangles(ret C.Rects) []image.Rectangle { 2354 | cArray := ret.rects 2355 | length := int(ret.length) 2356 | hdr := reflect.SliceHeader{ 2357 | Data: uintptr(unsafe.Pointer(cArray)), 2358 | Len: length, 2359 | Cap: length, 2360 | } 2361 | s := *(*[]C.Rect)(unsafe.Pointer(&hdr)) 2362 | 2363 | rects := make([]image.Rectangle, length) 2364 | for i, r := range s { 2365 | rects[i] = image.Rect(int(r.x), int(r.y), int(r.x+r.width), int(r.y+r.height)) 2366 | } 2367 | return rects 2368 | } 2369 | 2370 | func toRect(rect C.Rect) image.Rectangle { 2371 | return image.Rect(int(rect.x), int(rect.y), int(rect.x+rect.width), int(rect.y+rect.height)) 2372 | } 2373 | 2374 | func toCPoints(points []image.Point) C.struct_Points { 2375 | cPointSlice := make([]C.struct_Point, len(points)) 2376 | for i, point := range points { 2377 | cPointSlice[i] = C.struct_Point{ 2378 | x: C.int(point.X), 2379 | y: C.int(point.Y), 2380 | } 2381 | } 2382 | 2383 | return C.struct_Points{ 2384 | points: (*C.Point)(&cPointSlice[0]), 2385 | length: C.int(len(points)), 2386 | } 2387 | } 2388 | 2389 | func toCPoints2f(points []Point2f) C.struct_Points2f { 2390 | cPointSlice := make([]C.struct_Point2f, len(points)) 2391 | for i, point := range points { 2392 | cPointSlice[i] = C.struct_Point2f{ 2393 | x: C.float(point.X), 2394 | y: C.float(point.Y), 2395 | } 2396 | } 2397 | 2398 | return C.struct_Points2f{ 2399 | points: (*C.Point2f)(&cPointSlice[0]), 2400 | length: C.int(len(points)), 2401 | } 2402 | } 2403 | 2404 | func toCStrings(strs []string) C.struct_CStrings { 2405 | cStringsSlice := make([]*C.char, len(strs)) 2406 | for i, s := range strs { 2407 | cStringsSlice[i] = C.CString(s) 2408 | } 2409 | 2410 | return C.struct_CStrings{ 2411 | strs: (**C.char)(&cStringsSlice[0]), 2412 | length: C.int(len(strs)), 2413 | } 2414 | } 2415 | 2416 | // RowRange creates a matrix header for the specified row span. 2417 | // 2418 | // For further details, please see: 2419 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#aa6542193430356ad631a9beabc624107 2420 | // 2421 | func (m *Mat) RowRange(start, end int) Mat { 2422 | return newMat(C.Mat_rowRange(m.p, C.int(start), C.int(end))) 2423 | } 2424 | 2425 | // ColRange creates a matrix header for the specified column span. 2426 | // 2427 | // For further details, please see: 2428 | // https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#aadc8f9210fe4dec50513746c246fa8d9 2429 | // 2430 | func (m *Mat) ColRange(start, end int) Mat { 2431 | return newMat(C.Mat_colRange(m.p, C.int(start), C.int(end))) 2432 | } 2433 | 2434 | // RNG Random Number Generator. 2435 | // It encapsulates the state (currently, a 64-bit integer) and 2436 | // has methods to return scalar random values and to fill arrays 2437 | // with random values 2438 | // 2439 | // For further details, please see: 2440 | // https://docs.opencv.org/master/d1/dd6/classcv_1_1RNG.html 2441 | // 2442 | type RNG struct { 2443 | p C.RNG 2444 | } 2445 | 2446 | type RNGDistType int 2447 | 2448 | const ( 2449 | // Uniform distribution 2450 | RNGDistUniform RNGDistType = 0 2451 | // Normal distribution 2452 | RNGDistNormal RNGDistType = 1 2453 | ) 2454 | 2455 | // TheRNG Returns the default random number generator. 2456 | // 2457 | // For further details, please see: 2458 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga75843061d150ad6564b5447e38e57722 2459 | // 2460 | func TheRNG() RNG { 2461 | return RNG{ 2462 | p: C.TheRNG(), 2463 | } 2464 | } 2465 | 2466 | // TheRNG Sets state of default random number generator. 2467 | // 2468 | // For further details, please see: 2469 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga757e657c037410d9e19e819569e7de0f 2470 | // 2471 | func SetRNGSeed(seed int) { 2472 | C.SetRNGSeed(C.int(seed)) 2473 | } 2474 | 2475 | // Fill Fills arrays with random numbers. 2476 | // 2477 | // For further details, please see: 2478 | // https://docs.opencv.org/master/d1/dd6/classcv_1_1RNG.html#ad26f2b09d9868cf108e84c9814aa682d 2479 | // 2480 | func (r *RNG) Fill(mat *Mat, distType RNGDistType, a, b float64, saturateRange bool) { 2481 | C.RNG_Fill(r.p, mat.p, C.int(distType), C.double(a), C.double(b), C.bool(saturateRange)) 2482 | } 2483 | 2484 | // Gaussian Returns the next random number sampled from 2485 | // the Gaussian distribution. 2486 | // 2487 | // For further details, please see: 2488 | // https://docs.opencv.org/master/d1/dd6/classcv_1_1RNG.html#a8df8ce4dc7d15916cee743e5a884639d 2489 | // 2490 | func (r *RNG) Gaussian(sigma float64) float64 { 2491 | return float64(C.RNG_Gaussian(r.p, C.double(sigma))) 2492 | } 2493 | 2494 | // Next The method updates the state using the MWC algorithm 2495 | // and returns the next 32-bit random number. 2496 | // 2497 | // For further details, please see: 2498 | // https://docs.opencv.org/master/d1/dd6/classcv_1_1RNG.html#a8df8ce4dc7d15916cee743e5a884639d 2499 | // 2500 | func (r *RNG) Next() uint { 2501 | return uint(C.RNG_Next(r.p)) 2502 | } 2503 | 2504 | // RandN Fills the array with normally distributed random numbers. 2505 | // 2506 | // For further details, please see: 2507 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#gaeff1f61e972d133a04ce3a5f81cf6808 2508 | // 2509 | func RandN(mat *Mat, mean, stddev Scalar) { 2510 | meanVal := C.struct_Scalar{ 2511 | val1: C.double(mean.Val1), 2512 | val2: C.double(mean.Val2), 2513 | val3: C.double(mean.Val3), 2514 | val4: C.double(mean.Val4), 2515 | } 2516 | stddevVal := C.struct_Scalar{ 2517 | val1: C.double(stddev.Val1), 2518 | val2: C.double(stddev.Val2), 2519 | val3: C.double(stddev.Val3), 2520 | val4: C.double(stddev.Val4), 2521 | } 2522 | 2523 | C.RandN(mat.p, meanVal, stddevVal) 2524 | } 2525 | 2526 | // RandShuffle Shuffles the array elements randomly. 2527 | // 2528 | // For further details, please see: 2529 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga6a789c8a5cb56c6dd62506179808f763 2530 | // 2531 | func RandShuffle(mat *Mat) { 2532 | C.RandShuffle(mat.p) 2533 | } 2534 | 2535 | // RandShuffleWithParams Shuffles the array elements randomly. 2536 | // 2537 | // For further details, please see: 2538 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga6a789c8a5cb56c6dd62506179808f763 2539 | // 2540 | func RandShuffleWithParams(mat *Mat, iterFactor float64, rng RNG) { 2541 | C.RandShuffleWithParams(mat.p, C.double(iterFactor), rng.p) 2542 | } 2543 | 2544 | // RandU Generates a single uniformly-distributed random 2545 | // number or an array of random numbers. 2546 | // 2547 | // For further details, please see: 2548 | // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga1ba1026dca0807b27057ba6a49d258c0 2549 | // 2550 | func RandU(mat *Mat, low, high Scalar) { 2551 | lowVal := C.struct_Scalar{ 2552 | val1: C.double(low.Val1), 2553 | val2: C.double(low.Val2), 2554 | val3: C.double(low.Val3), 2555 | val4: C.double(low.Val4), 2556 | } 2557 | highVal := C.struct_Scalar{ 2558 | val1: C.double(high.Val1), 2559 | val2: C.double(high.Val2), 2560 | val3: C.double(high.Val3), 2561 | val4: C.double(high.Val4), 2562 | } 2563 | 2564 | C.RandU(mat.p, lowVal, highVal) 2565 | } 2566 | 2567 | type NativeByteBuffer struct { 2568 | // std::vector is build of 3 pointers And this will not change ever. 2569 | stdVectorOpaq [3]uintptr 2570 | } 2571 | 2572 | func newNativeByteBuffer() *NativeByteBuffer { 2573 | buffer := &NativeByteBuffer{} 2574 | C.StdByteVectorInitialize(buffer.nativePointer()) 2575 | return buffer 2576 | } 2577 | 2578 | func (buffer *NativeByteBuffer) nativePointer() unsafe.Pointer { 2579 | return unsafe.Pointer(&buffer.stdVectorOpaq[0]) 2580 | } 2581 | 2582 | func (buffer *NativeByteBuffer) dataPointer() unsafe.Pointer { 2583 | return unsafe.Pointer(C.StdByteVectorData(buffer.nativePointer())) 2584 | } 2585 | 2586 | // GetBytes returns slice of bytes backed by native buffer 2587 | func (buffer *NativeByteBuffer) GetBytes() []byte { 2588 | var result []byte 2589 | sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&result)) 2590 | vectorLen := int(C.StdByteVectorLen(buffer.nativePointer())) 2591 | sliceHeader.Cap = vectorLen 2592 | sliceHeader.Len = vectorLen 2593 | sliceHeader.Data = uintptr(buffer.dataPointer()) 2594 | return result 2595 | } 2596 | 2597 | // Len - returns length in bytes of underlying buffer 2598 | func (buffer *NativeByteBuffer) Len() int { 2599 | return int(C.StdByteVectorLen(buffer.nativePointer())) 2600 | } 2601 | 2602 | // Close the buffer releasing all its resources 2603 | func (buffer *NativeByteBuffer) Close() { 2604 | C.StdByteVectorFree(buffer.nativePointer()) 2605 | } 2606 | // Points2fVector is a wrapper around a std::vector< std::vector< cv::Point2f > >* 2607 | type Points2fVector struct { 2608 | p C.Points2fVector 2609 | } 2610 | 2611 | // NewPoints2fVector returns a new empty Points2fVector. 2612 | func NewPoints2fVector() Points2fVector { 2613 | return Points2fVector{p: C.Points2fVector_New()} 2614 | } 2615 | 2616 | // NewPoints2fVectorFromPoints returns a new Points2fVector that has been 2617 | // initialized to a slice of slices of Point2f. 2618 | func NewPoints2fVectorFromPoints(pts [][]Point2f) Points2fVector { 2619 | pvf := NewPoints2fVector() 2620 | for j := 0;j pvs.Size() { 2656 | return Point2fVector{} 2657 | } 2658 | return Point2fVector{p : C.Points2fVector_At(pvs.p, C.int(idx))} 2659 | } 2660 | 2661 | // Append appends a Point2fVector at end of the Points2fVector. 2662 | func (pvs Points2fVector) Append(pv Point2fVector) { 2663 | if !pv.IsNil() { 2664 | C.Points2fVector_Append(pvs.p, pv.p) 2665 | } 2666 | } 2667 | 2668 | // Close closes and frees memory for this Points2fVector. 2669 | func (pvs Points2fVector) Close() { 2670 | C.Points2fVector_Close(pvs.p) 2671 | } 2672 | 2673 | type Point3f struct { 2674 | X float32 2675 | Y float32 2676 | Z float32 2677 | } 2678 | 2679 | func NewPoint3f(x, y, z float32) Point3f { 2680 | return Point3f{x, y, z} 2681 | } 2682 | 2683 | // Point3fVector is a wrapper around a std::vector< cv::Point3f >* 2684 | type Point3fVector struct { 2685 | p C.Point3fVector 2686 | } 2687 | 2688 | // NewPoint3fVector returns a new empty Point3fVector. 2689 | func NewPoint3fVector() Point3fVector { 2690 | return Point3fVector{p: C.Point3fVector_New()} 2691 | } 2692 | 2693 | // NewPoint3fVectorFromPoints returns a new Point3fVector that has been 2694 | // initialized to a slice of image.Point. 2695 | func NewPoint3fVectorFromPoints(pts []Point3f) Point3fVector { 2696 | p := (*C.struct_Point3f)(C.malloc(C.size_t(C.sizeof_struct_Point3f * len(pts)))) 2697 | defer C.free(unsafe.Pointer(p)) 2698 | 2699 | h := &reflect.SliceHeader{ 2700 | Data: uintptr(unsafe.Pointer(p)), 2701 | Len: len(pts), 2702 | Cap: len(pts), 2703 | } 2704 | pa := *(*[]C.Point3f)(unsafe.Pointer(h)) 2705 | 2706 | for j, point := range pts { 2707 | pa[j] = C.struct_Point3f{ 2708 | x: C.float(point.X), 2709 | y: C.float(point.Y), 2710 | z: C.float(point.Z), 2711 | } 2712 | } 2713 | 2714 | cPoints := C.struct_Points3f{ 2715 | points: (*C.Point3f)(p), 2716 | length: C.int(len(pts)), 2717 | } 2718 | 2719 | return Point3fVector{p: C.Point3fVector_NewFromPoints(cPoints)} 2720 | } 2721 | 2722 | // NewPoint3fVectorFromMat returns a new Point3fVector that has been 2723 | // wrapped around a Mat of type CV_32FC3 with a single columm. 2724 | func NewPoint3fVectorFromMat(mat Mat) Point3fVector { 2725 | return Point3fVector{p: C.Point3fVector_NewFromMat(mat.p)} 2726 | } 2727 | 2728 | // IsNil checks the CGo pointer in the Point3fVector. 2729 | func (pfv Point3fVector) IsNil() bool { 2730 | return pfv.p == nil 2731 | } 2732 | 2733 | // Size returns how many Point are in the Point3fVector. 2734 | func (pfv Point3fVector) Size() int { 2735 | return int(C.Point3fVector_Size(pfv.p)) 2736 | } 2737 | 2738 | // At returns the Point3f 2739 | func (pfv Point3fVector) At(idx int) Point3f { 2740 | if idx > pfv.Size() { 2741 | return Point3f{} 2742 | } 2743 | cp := C.Point3fVector_At(pfv.p, C.int(idx)) 2744 | return Point3f{X: float32(cp.x), Y: float32(cp.y), Z: float32(cp.z)} 2745 | } 2746 | 2747 | func (pfv Point3fVector) Append(point Point3f) { 2748 | C.Point3fVector_Append(pfv.p, C.Point3f{ 2749 | x: C.float(point.X), 2750 | y: C.float(point.Y), 2751 | z: C.float(point.Z), 2752 | }); 2753 | } 2754 | 2755 | // ToPoints returns a slice of Point3f for the data in this Point3fVector. 2756 | func (pfv Point3fVector) ToPoints() []Point3f { 2757 | points := make([]Point3f, pfv.Size()) 2758 | for j := 0; j < pfv.Size(); j++ { 2759 | points[j] = pfv.At(j) 2760 | } 2761 | return points 2762 | } 2763 | 2764 | // Close closes and frees memory for this Point3fVector. 2765 | func (pfv Point3fVector) Close() { 2766 | C.Point3fVector_Close(pfv.p) 2767 | } 2768 | 2769 | // Points3fVector is a wrapper around a std::vector< std::vector< cv::Point3f > >* 2770 | type Points3fVector struct { 2771 | p C.Points3fVector 2772 | } 2773 | 2774 | // NewPoints3fVector returns a new empty Points3fVector. 2775 | func NewPoints3fVector() Points3fVector { 2776 | return Points3fVector{p: C.Points3fVector_New()} 2777 | } 2778 | 2779 | // NewPoints3fVectorFromPoints returns a new Points3fVector that has been 2780 | // initialized to a slice of slices of Point3f. 2781 | func NewPoints3fVectorFromPoints(pts [][]Point3f) Points3fVector { 2782 | pvf := NewPoints3fVector() 2783 | for j := 0;j pvs.Size() { 2815 | return Point3fVector{} 2816 | } 2817 | return Point3fVector{p : C.Points3fVector_At(pvs.p, C.int(idx))} 2818 | } 2819 | 2820 | // Append appends a Point3fVector at end of the Points3fVector. 2821 | func (pvs Points3fVector) Append(pv Point3fVector) { 2822 | if !pv.IsNil() { 2823 | C.Points3fVector_Append(pvs.p, pv.p) 2824 | } 2825 | } 2826 | 2827 | // Close closes and frees memory for this Points3fVector. 2828 | func (pvs Points3fVector) Close() { 2829 | C.Points3fVector_Close(pvs.p) 2830 | } --------------------------------------------------------------------------------