added contrib.xobjdetect

This commit is contained in:
diegohce
2025-01-21 08:48:43 -03:00
committed by Diego Cena
parent 4e29817ab8
commit 084788b79a
7 changed files with 239 additions and 1 deletions

View File

@@ -350,5 +350,5 @@ Your pull requests will be greatly appreciated!
- [X] **wechat_qrcode. WeChat QR code detector for detecting and parsing QR code**
- [ ] **xfeatures2d. Extra 2D Features Framework - WORK STARTED**
- [ ] **ximgproc. Extended Image Processing - WORK STARTED**
- [ ] xobjdetect. Extended object detection
- [X] xobjdetect. Extended object detection
- [X] **xphoto. Additional photo processing algorithms**

51
contrib/xobjdetect.cpp Normal file
View File

@@ -0,0 +1,51 @@
#include "xobjdetect.h"
WBDetector WBDetector_Create(){
return new cv::Ptr<cv::xobjdetect::WBDetector>(cv::xobjdetect::WBDetector::create());
}
void WBDetector_Close(WBDetector det){
delete det;
}
WBDetector_detect_result WBDetector_Detect(WBDetector det, Mat img){
std::vector<cv::Rect> bb;
std::vector<double> conf;
WBDetector_detect_result result;
(*det)->detect(*img, bb, conf);
Rect* result_rects = (Rect*)malloc(bb.size()*sizeof(Rect));
float* result_confs = (float*)malloc(conf.size()*sizeof(float));
for(int i = 0; i < bb.size(); i ++) {
result_rects[i].x = bb[i].x;
result_rects[i].y = bb[i].y;
result_rects[i].width = bb[i].width;
result_rects[i].height = bb[i].height;
}
for(int i = 0; i < conf.size(); i ++){
result_confs[i] = conf[i];
}
result.bboxes.rects = result_rects;
result.bboxes.length = bb.size();
result.confidences.val = result_confs;
result.confidences.length = conf.size();
return result;
}
void WBDetector_Read(WBDetector det, FileNode node){
(*det)->read(*node);
}
void WBDetector_Train(WBDetector det, const char* pos_samples, const char* neg_imgs){
(*det)->train(pos_samples, neg_imgs);
}
void WBDetector_Write(WBDetector det, FileStorage fs){
(*det)->write(*fs);
}

108
contrib/xobjdetect.go Normal file
View File

@@ -0,0 +1,108 @@
package contrib
/*
#include <stdlib.h>
#include "xobjdetect.h"
*/
import "C"
import (
"image"
"unsafe"
"gocv.io/x/gocv"
)
// WBDetector is a wrapper around the cv::xobjdetect::WBDetector.
type WBDetector struct {
p C.WBDetector
}
// NewWBDetector Creates a new WBDetector
//
// For further details, please see:
// https://docs.opencv.org/4.x/de/d0e/classcv_1_1xobjdetect_1_1WBDetector.html#a58377ae61694aac08ad842ac830972d9
func NewWBDetector() WBDetector {
p := C.WBDetector_Create()
return WBDetector{p: p}
}
// Close Releases WBDetector allocated resources.
func (det *WBDetector) Close() {
C.WBDetector_Close(det.p)
}
// Detect Detect objects on image using WaldBoost detector
//
// img: Input image for detection
//
// Returns:
//
// Bounding boxes coordinates and
// Confidence values for bounding boxes output vector
//
// For further details, please see:
// https://docs.opencv.org/4.x/de/d0e/classcv_1_1xobjdetect_1_1WBDetector.html#ad19680e6545f49a9ca42dfc3457319e2
func (det *WBDetector) Detect(img gocv.Mat) ([]image.Rectangle, []float32) {
result := C.WBDetector_Detect(det.p, C.Mat(img.Ptr()))
defer C.free(unsafe.Pointer(result.bboxes.rects))
defer C.free(unsafe.Pointer(result.confidences.val))
cRects := unsafe.Slice(result.bboxes.rects, result.bboxes.length)
cConfs := unsafe.Slice(result.confidences.val, result.confidences.length)
goRects := make([]image.Rectangle, int(result.bboxes.length))
goConfs := make([]float32, int(result.confidences.length))
for i := 0; i < int(result.bboxes.length); i++ {
r := image.Rect(int(cRects[i].x),
int(cRects[i].y),
int(cRects[i].width),
int(cRects[i].height))
goRects = append(goRects, r)
}
for i := 0; i < int(result.confidences.length); i++ {
goConfs[i] = float32(cConfs[i])
}
return goRects, goConfs
}
// Read Read detector from gocv.FileNode
//
// For further details, please see:
// https://docs.opencv.org/4.x/de/d0e/classcv_1_1xobjdetect_1_1WBDetector.html#aef2df760f45d25aade518196986e139f
func (det *WBDetector) Read(node *gocv.FileNode) {
C.WBDetector_Read(det.p, C.FileNode(node.Ptr()))
}
// Train WaldBoost detector.
//
// Parameters:
//
// posSamples: Path to directory with cropped positive samples
//
// negImgs: Path to directory with negative (background) images
//
// For further details, please see:
// https://docs.opencv.org/4.x/de/d0e/classcv_1_1xobjdetect_1_1WBDetector.html#a3720fb425a2d16f6cd0625a2d8bc563e
func (det *WBDetector) Train(posSamples string, negImgs string) {
pos_samples := C.CString(posSamples)
neg_imgs := C.CString(negImgs)
defer C.free(unsafe.Pointer(pos_samples))
defer C.free(unsafe.Pointer(neg_imgs))
C.WBDetector_Train(det.p, pos_samples, neg_imgs)
}
// Write detector to gocv.FileStorage.
//
// For further details, please see:
// https://docs.opencv.org/4.x/de/d0e/classcv_1_1xobjdetect_1_1WBDetector.html#a7d85338895707904ae1ddb4374ec8dac
func (det *WBDetector) Write(fs *gocv.FileStorage) {
C.WBDetector_Write(det.p, C.FileStorage(fs.Ptr()))
}

35
contrib/xobjdetect.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef _OPENCV3_XOBJDETECT_H_
#define _OPENCV3_XOBJDETECT_H_
#ifdef __cplusplus
#include <opencv2/opencv.hpp>
#include <opencv2/xobjdetect.hpp>
extern "C" {
#endif
#include "../core.h"
#include "../persistence.h"
typedef struct WBDetector_detect_result_t {
Rects bboxes;
FloatVector confidences;
} WBDetector_detect_result;
#ifdef __cplusplus
typedef cv::Ptr<cv::xobjdetect::WBDetector>* WBDetector;
#else
typedef void* WBDetector;
#endif
WBDetector WBDetector_Create();
void WBDetector_Close(WBDetector det);
WBDetector_detect_result WBDetector_Detect(WBDetector det, Mat img);
void WBDetector_Read(WBDetector det, FileNode node);
void WBDetector_Train(WBDetector det, const char* pos_samples, const char* neg_imgs);
void WBDetector_Write(WBDetector det, FileStorage fs);
#ifdef __cplusplus
}
#endif
#endif //_OPENCV3_XOBJDETECT_H_

View File

@@ -0,0 +1,36 @@
package contrib
import (
"testing"
"gocv.io/x/gocv"
)
func TestWBDetector(t *testing.T) {
img := gocv.IMRead("../images/face.jpg", gocv.IMReadAnyColor)
if img.Empty() {
t.Error("xobjdetect: cannot read image")
}
det := NewWBDetector()
defer det.Close()
det.Train("../images/gocvlogo.jpg", "../images/gocvlogo.png")
det.Detect(img)
fs := gocv.NewFileStorageWithParams("../testdata/WBDetector.json", gocv.FileStorageModeWrite, "utf-8")
defer fs.Close()
fs.StartWriteStruct("gocv", gocv.FileNodeTypeSeq, "model")
det.Write(fs)
fs.EndWriteStruct()
node := fs.GetFirstTopLevelNode()
det.Read(node)
}

View File

@@ -32,6 +32,10 @@ type FileNode struct {
p C.FileNode
}
func (fn *FileNode) Ptr() C.FileNode {
return fn.p
}
func (fn *FileNode) Empty() bool {
return bool(C.FileNode_Empty(fn.p))
}

View File

@@ -200,3 +200,7 @@ func (fs *FileStorage) Root(streamIdx int) *FileNode {
node_p := C.FileStorage_Root(fs.p, C.int(streamIdx))
return &FileNode{p: node_p}
}
func (fs *FileStorage) Ptr() C.FileStorage {
return fs.p
}