Skip to content

Commit

Permalink
added contrib.xobjdetect
Browse files Browse the repository at this point in the history
  • Loading branch information
diegohce committed Jan 21, 2025
1 parent 4e29817 commit 084788b
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 1 deletion.
2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 51 additions & 0 deletions contrib/xobjdetect.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 108 additions & 0 deletions contrib/xobjdetect.go
Original file line number Diff line number Diff line change
@@ -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 changes: 35 additions & 0 deletions contrib/xobjdetect.h
Original file line number Diff line number Diff line change
@@ -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_
36 changes: 36 additions & 0 deletions contrib/xobjdetect_test.go
Original file line number Diff line number Diff line change
@@ -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)

}
4 changes: 4 additions & 0 deletions persistence_filenode.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down
4 changes: 4 additions & 0 deletions persistence_filestorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit 084788b

Please sign in to comment.