148 lines
3.1 KiB
Go
148 lines
3.1 KiB
Go
package opencv
|
|
|
|
/*
|
|
#cgo CXXFLAGS: -std=c++17 -I/usr/include/opencv4
|
|
#cgo CPPFLAGS: -I/usr/include/opencv4
|
|
#cgo linux LDFLAGS: -L/usr/lib -lopencv_core -lopencv_imgproc -lopencv_imgcodecs -lopencv_objdetect
|
|
#cgo darwin CPPFLAGS: -I/usr/local/include/opencv4
|
|
#cgo darwin LDFLAGS: -lopencv_core -lopencv_imgproc -lopencv_imgcodecs -lopencv_objdetect
|
|
|
|
#include <stdlib.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
// 图像结构
|
|
typedef struct {
|
|
unsigned char* data;
|
|
int width;
|
|
int height;
|
|
int channels;
|
|
} Image;
|
|
|
|
// 图像操作
|
|
Image* cv_imdecode(const unsigned char* buf, size_t size);
|
|
void cv_image_free(Image* img);
|
|
|
|
// 滑块匹配
|
|
int cv_slider_match(const Image* target, const Image* background, int* out_x);
|
|
int cv_slider_comparison(const Image* target, const Image* background, int* out_x);
|
|
|
|
// 旋转检测
|
|
float cv_detect_rotation(const Image* img);
|
|
|
|
// 模板匹配
|
|
int cv_template_match(const Image* src, const Image* templ, double* max_val, int* max_x, int* max_y);
|
|
|
|
// 特征点检测
|
|
int cv_detect_features(const Image* img, int** points_x, int** points_y, int* count);
|
|
|
|
// 图像相似度
|
|
float cv_compare_similarity(const Image* img1, const Image* img2);
|
|
|
|
// 错误信息
|
|
const char* cv_get_last_error();
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
*/
|
|
import "C"
|
|
import (
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"unsafe"
|
|
)
|
|
|
|
// Image 封装图像数据
|
|
type Image struct {
|
|
img *C.Image
|
|
}
|
|
|
|
// DecodeFromBase64 从 Base64 解码图像
|
|
func DecodeFromBase64(data string) (*Image, error) {
|
|
decoded, err := base64.StdEncoding.DecodeString(data)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("base64 解码失败: %v", err)
|
|
}
|
|
|
|
img := C.cv_imdecode(
|
|
(*C.uchar)(unsafe.Pointer(&decoded[0])),
|
|
C.size_t(len(decoded)),
|
|
)
|
|
|
|
if img == nil {
|
|
return nil, errors.New(C.GoString(C.cv_get_last_error()))
|
|
}
|
|
|
|
return &Image{img: img}, nil
|
|
}
|
|
|
|
// Free 释放图像内存
|
|
func (i *Image) Free() {
|
|
if i.img != nil {
|
|
C.cv_image_free(i.img)
|
|
i.img = nil
|
|
}
|
|
}
|
|
|
|
// Width 获取宽度
|
|
func (i *Image) Width() int {
|
|
return int(i.img.width)
|
|
}
|
|
|
|
// Height 获取高度
|
|
func (i *Image) Height() int {
|
|
return int(i.img.height)
|
|
}
|
|
|
|
// SliderMatch 滑块缺口匹配
|
|
func SliderMatch(target, background *Image) (int, error) {
|
|
var outX C.int
|
|
|
|
result := C.cv_slider_match(
|
|
(*C.Image)(target.img),
|
|
(*C.Image)(background.img),
|
|
&outX,
|
|
)
|
|
|
|
if result != 0 {
|
|
return 0, errors.New(C.GoString(C.cv_get_last_error()))
|
|
}
|
|
|
|
return int(outX), nil
|
|
}
|
|
|
|
// SliderComparison 阴影滑块匹配
|
|
func SliderComparison(target, background *Image) (int, error) {
|
|
var outX C.int
|
|
|
|
result := C.cv_slider_comparison(
|
|
(*C.Image)(target.img),
|
|
(*C.Image)(background.img),
|
|
&outX,
|
|
)
|
|
|
|
if result != 0 {
|
|
return 0, errors.New(C.GoString(C.cv_get_last_error()))
|
|
}
|
|
|
|
return int(outX), nil
|
|
}
|
|
|
|
// DetectRotation 检测旋转角度
|
|
func DetectRotation(img *Image) (float32, error) {
|
|
angle := C.cv_detect_rotation((*C.Image)(img.img))
|
|
return float32(angle), nil
|
|
}
|
|
|
|
// CompareSimilarity 比较图像相似度
|
|
func CompareSimilarity(img1, img2 *Image) (float32, error) {
|
|
similarity := C.cv_compare_similarity(
|
|
(*C.Image)(img1.img),
|
|
(*C.Image)(img2.img),
|
|
)
|
|
return float32(similarity), nil
|
|
} |