Skip to content

Commit e9ad6e5

Browse files
Merge pull request #614 from foxxyz/feature/seamlessclone
Add `cv.seamlessClone`
2 parents 4425af5 + 6a48b9c commit e9ad6e5

File tree

12 files changed

+116
-3
lines changed

12 files changed

+116
-3
lines changed

binding.gyp

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"cc/io/VideoWriter.cc",
4242
"cc/photo/photo.cc",
4343
"cc/photo/photoConstants.cc",
44+
"cc/photo/MatPhoto.cc",
4445
"cc/video/video.cc",
4546
"cc/video/BackgroundSubtractor.cc",
4647
"cc/video/BackgroundSubtractorMOG2.cc",

cc/core/Mat.cc

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#ifdef HAVE_OPENCV_IMGPROC
1010
#include "../imgproc/MatImgproc.h"
1111
#endif
12+
#ifdef HAVE_OPENCV_PHOTO
13+
#include "../photo/MatPhoto.h"
14+
#endif
1215
#ifdef HAVE_OPENCV_XIMGPROC
1316
#include "../ximgproc/MatXimgproc.h"
1417
#endif
@@ -126,6 +129,9 @@ NAN_MODULE_INIT(Mat::Init) {
126129
#ifdef HAVE_OPENCV_IMGPROC
127130
MatImgproc::Init(ctor);
128131
#endif
132+
#ifdef HAVE_OPENCV_PHOTO
133+
MatPhoto::Init(ctor);
134+
#endif
129135
#ifdef HAVE_OPENCV_XIMGPROC
130136
MatXimgproc::Init(ctor);
131137
#endif

cc/photo/MatPhoto.cc

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "opencv_modules.h"
2+
3+
#ifdef HAVE_OPENCV_PHOTO
4+
5+
#include "MatPhoto.h"
6+
#include "photoBindings.h"
7+
8+
void MatPhoto::Init(v8::Local<v8::FunctionTemplate> ctor) {
9+
Nan::SetPrototypeMethod(ctor, "seamlessClone", SeamlessClone);
10+
Nan::SetPrototypeMethod(ctor, "seamlessCloneAsync", SeamlessCloneAsync);
11+
};
12+
13+
NAN_METHOD(MatPhoto::SeamlessClone) {
14+
Mat::syncBinding<PhotoBindings::SeamlessClone>("SeamlessClone", info);
15+
}
16+
17+
NAN_METHOD(MatPhoto::SeamlessCloneAsync) {
18+
Mat::asyncBinding<PhotoBindings::SeamlessClone>("SeamlessClone", info);
19+
}
20+
21+
#endif

cc/photo/MatPhoto.h

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include "Mat.h"
2+
#include <opencv2/photo.hpp>
3+
4+
#ifndef __FF_MATPHOTO_H__
5+
#define __FF_MATPHOTO_H__
6+
7+
class MatPhoto {
8+
public:
9+
static void Init(v8::Local<v8::FunctionTemplate> ctor);
10+
11+
static NAN_METHOD(SeamlessClone);
12+
static NAN_METHOD(SeamlessCloneAsync);
13+
};
14+
15+
#endif

cc/photo/photo.cc

+10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ NAN_MODULE_INIT(Photo::Init) {
1212
Nan::SetMethod(target, "fastNlMeansDenoisingColoredAsync", FastNlMeansDenoisingColoredAsync);
1313
Nan::SetMethod(target, "inpaint", Inpaint);
1414
Nan::SetMethod(target, "inpaintAsync", InpaintAsync);
15+
Nan::SetMethod(target, "seamlessClone", SeamlessClone);
16+
Nan::SetMethod(target, "seamlessCloneAsync", SeamlessCloneAsync);
1517
};
1618

1719
NAN_METHOD(Photo::FastNlMeansDenoisingColored) {
@@ -46,4 +48,12 @@ NAN_METHOD(Photo::InpaintAsync) {
4648
);
4749
}
4850

51+
NAN_METHOD(Photo::SeamlessClone) {
52+
FF::syncBinding<PhotoBindings::SeamlessClone>("Photo", "SeamlessClone", info);
53+
}
54+
55+
NAN_METHOD(Photo::SeamlessCloneAsync) {
56+
FF::asyncBinding<PhotoBindings::SeamlessClone>("Photo", "SeamlessClone", info);
57+
}
58+
4959
#endif

cc/photo/photo.h

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class Photo {
1414
static NAN_METHOD(FastNlMeansDenoisingColoredAsync);
1515
static NAN_METHOD(Inpaint);
1616
static NAN_METHOD(InpaintAsync);
17+
static NAN_METHOD(SeamlessClone);
18+
static NAN_METHOD(SeamlessCloneAsync);
1719
};
1820

1921
#endif

cc/photo/photoBindings.h

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "CvBinding.h"
12
#include "photo.h"
23

34
#ifndef __FF_PHOTOBINDINGS_H_
@@ -86,7 +87,21 @@ namespace PhotoBindings {
8687
return Mat::Converter::wrap(dst);
8788
}
8889
};
89-
90+
91+
class SeamlessClone : public CvClassMethodBinding<Mat> {
92+
public:
93+
void createBinding(std::shared_ptr<FF::Value<cv::Mat>> self) {
94+
auto dst = req<Mat::Converter>();
95+
auto mask = req<Mat::Converter>();
96+
auto p = req<Point2::Converter>();
97+
auto flags = req<FF::IntConverter>();
98+
auto blend = ret<Mat::Converter>("blend");
99+
100+
executeBinding = [=]() {
101+
cv::seamlessClone(self->ref(), dst->ref(), mask->ref(), p->ref(), blend->ref(), flags->ref());
102+
};
103+
};
104+
};
90105

91106
}
92107

cc/photo/photoConstants.cc

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ using namespace cv;
99
void PhotoConstants::Init(v8::Local<v8::Object> target) {
1010
FF_SET_CV_CONSTANT(target, INPAINT_NS);
1111
FF_SET_CV_CONSTANT(target, INPAINT_TELEA);
12+
FF_SET_CV_CONSTANT(target, NORMAL_CLONE);
13+
FF_SET_CV_CONSTANT(target, MIXED_CLONE);
14+
FF_SET_CV_CONSTANT(target, MONOCHROME_TRANSFER);
1215
}
1316

1417
#endif

lib/typings/Mat.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ export class Mat {
263263
rqDecomp3x3Async(): Promise<{ returnValue: Vec3, mtxR: Mat, mtxQ: Mat, Qx: Mat, Qy: Mat, Qz: Mat }>;
264264
scharr(ddepth: number, dx: number, dy: number, scale?: number, delta?: number, borderType?: number): Mat;
265265
scharrAsync(ddepth: number, dx: number, dy: number, scale?: number, delta?: number, borderType?: number): Promise<Mat>;
266+
seamlessClone(dst: Mat, mask: Mat, p: Point2, flags: number): Mat;
267+
seamlessCloneAsync(dst: Mat, mask: Mat, p: Point2, flags: number): Promise<Mat>;
266268
sepFilter2D(ddepth: number, kernelX: Mat, kernelY: Mat, anchor?: Point2, delta?: number, borderType?: number): Mat;
267269
sepFilter2DAsync(ddepth: number, kernelX: Mat, kernelY: Mat, anchor?: Point2, delta?: number, borderType?: number): Promise<Mat>;
268270
set(row: number, col: number, value: number): void;

lib/typings/constants.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,8 @@ export const LINE_4: number;
435435
export const LINE_8: number;
436436
export const LINE_AA: number;
437437
export const LMEDS: number;
438+
export const MIXED_CLONE: number;
439+
export const MONOCHROME_TRANSFER: number;
438440
export const MORPH_BLACKHAT: number;
439441
export const MORPH_CLOSE: number;
440442
export const MORPH_CROSS: number;
@@ -455,6 +457,7 @@ export const NORM_L2SQR: number;
455457
export const NORM_MINMAX: number;
456458
export const NORM_RELATIVE: number;
457459
export const NORM_const_MASK: number;
460+
export const NORMAL_CLONE: number;
458461
export const RANSAC: number;
459462
export const REGULAR: number;
460463
export const RETR_CCOMP: number;

lib/typings/cv.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ export function reduce(mat: Mat, dim: number, rtype: number, dtype?: number): Ma
163163
export function reduceAsync(mat: Mat, dim: number, rtype: number, dtype?: number): Promise<Mat>;
164164
export function sampsonDistance(pt1: Vec2, pt2: Vec2, F: Mat): number;
165165
export function sampsonDistanceAsync(pt1: Vec2, pt2: Vec2, F: Mat): Promise<number>;
166+
export function seamlessClone(src: Mat, dst: Mat, mask: Mat, p: Point2, flags: number): Mat;
167+
export function seamlessCloneAsync(src: Mat, dst: Mat, mask: Mat, p: Point2, flags: number): Promise<Mat>;
166168
export function solve(mat: Mat, mat2: Mat, flags?: number): Mat;
167169
export function solveAsync(mat: Mat, mat2: Mat, flags?: number): Promise<Mat>;
168170
export function solveP3P(objectPoints: Point3[], imagePoints: Point2[], cameraMatrix: Mat, distCoeffs: number[], flags?: number): { returnValue: boolean, rvecs: Mat[], tvecs: Mat[] };

test/tests/photo/index.js

+35-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports = function ({ cv, utils }) {
88
assertMetaData,
99
funcShouldRequireArgs,
1010
readTestImage,
11-
generateAPITests
11+
generateClassMethodTests
1212
} = utils;
1313

1414
describe('inpaint', () => {
@@ -59,6 +59,39 @@ module.exports = function ({ cv, utils }) {
5959
done();
6060
}).catch(done);
6161
});
62-
})
62+
});
63+
64+
describe('seamlessClone', () => {
65+
66+
it('should have constants', () => {
67+
expect(isNaN(cv.NORMAL_CLONE)).to.be.equal(false);
68+
expect(isNaN(cv.MIXED_CLONE)).to.be.equal(false);
69+
expect(isNaN(cv.MONOCHROME_TRANSFER)).to.be.equal(false);
70+
});
71+
72+
const src = new cv.Mat(5, 5, cv.CV_8UC3, [128, 128, 128]);
73+
const dest = new cv.Mat(10, 10, cv.CV_8UC3, [32, 32, 32]);
74+
const mask = new cv.Mat(5, 5, cv.CV_8UC3, [255, 255, 255]);
75+
const center = new cv.Point2(5, 5);
76+
const cloneType = cv.NORMAL_CLONE;
77+
78+
const expectOutput = (res) => {
79+
assertMetaData(res)(dest.rows, dest.cols, cv.CV_8UC3);
80+
};
81+
82+
generateClassMethodTests({
83+
getClassInstance: () => src,
84+
methodName: 'seamlessClone',
85+
classNameSpace: 'Mat',
86+
methodNameSpace: 'Photo',
87+
getRequiredArgs: () => ([
88+
dest,
89+
mask,
90+
center,
91+
cloneType
92+
]),
93+
expectOutput
94+
});
95+
});
6396

6497
};

0 commit comments

Comments
 (0)