org.bytedeco.javacv.Marker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javacv Show documentation
Show all versions of javacv Show documentation
Java interface to OpenCV and more
/*
* Copyright (C) 2009-2012 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bytedeco.javacv;
import java.nio.ByteBuffer;
import java.util.Arrays;
import static org.bytedeco.javacpp.ARToolKitPlus.*;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;
/**
*
* @author Samuel Audet
*/
public class Marker implements Cloneable {
public Marker(int id, double[] corners, double confidence) {
this.id = id;
this.corners = corners;
this.confidence = confidence;
}
public Marker(int id, double ... corners) {
this(id, corners, 1.0);
}
@Override public Marker clone() {
return new Marker(id, corners.clone(), confidence);
}
public int id;
public double[] corners;
public double confidence;
@Override public int hashCode() {
int hash = 7;
hash = 37 * hash + this.id;
hash = 37 * hash + (this.corners != null ? this.corners.hashCode() : 0);
return hash;
}
@Override public boolean equals(Object o) {
if (o instanceof Marker) {
Marker m = (Marker)o;
return m.id == id && Arrays.equals(m.corners, corners);
}
return false;
}
public double[] getCenter() {
double x = 0, y = 0;
if (true) {
// the centroid is not what we want as it does not remain at
// the same physical point under projective transformations..
// But it has the advantage of averaging noise better, and does
// give better results
for (int i = 0; i < 4; i++) {
x += corners[2*i ];
y += corners[2*i+1];
}
x /= 4;
y /= 4;
} else {
double x1 = corners[0]; double y1 = corners[1];
double x2 = corners[4]; double y2 = corners[5];
double x3 = corners[2]; double y3 = corners[3];
double x4 = corners[6]; double y4 = corners[7];
double u = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3))/
((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
x = x1 + u*(x2-x1);
y = y1 + u*(y2-y1);
}
return new double[] { x, y };
}
public IplImage getImage() {
return getImage(id);
}
private static IplImage imageCache[] = new IplImage[4096];
public static IplImage getImage(int id) {
if (imageCache[id] == null) {
imageCache[id] = IplImage.create(8, 8, IPL_DEPTH_8U, 1);
createImagePatternBCH(id, imageCache[id].getByteBuffer());
}
return imageCache[id];
}
private static final double[] src = { 0, 0, 8, 0, 8, 8, 0, 8 };
public void draw(IplImage image) {
draw(image, CvScalar.BLACK, 1, null);
}
public void draw(IplImage image, CvScalar color, double scale, CvMat prewarp) {
draw(image, color, scale, scale, prewarp);
}
private static ThreadLocal
H3x3 = CvMat.createThreadLocal(3, 3),
srcPts4x1 = CvMat.createThreadLocal(4, 1, CV_64F, 2),
dstPts4x1 = CvMat.createThreadLocal(4, 1, CV_64F, 2);
public void draw(IplImage image, CvScalar color, double scaleX, double scaleY, CvMat prewarp) {
CvMat H = H3x3.get();
JavaCV.getPerspectiveTransform(src, corners, H);
if (prewarp != null) {
cvGEMM(prewarp, H, 1, null, 0, H, 0);
}
IplImage marker = getImage();
ByteBuffer mbuf = marker.getByteBuffer();
CvMat srcPts = srcPts4x1.get();
CvMat dstPts = dstPts4x1.get();
CvPoint tempPts = new CvPoint(4);
int h = marker.height();
int w = marker.width();
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (mbuf.get(y*w + x) == 0) {
srcPts.put((double)x, y, x+1, y, x+1, y+1, x, y+1);
//System.out.println("srcPts" + srcPts);
cvPerspectiveTransform(srcPts, dstPts, H);
//System.out.println("dstPts" + dstPts);
double centerx = 0, centery = 0;
for (int i = 0; i < 4; i++) {
centerx += dstPts.get(i*2 );
centery += dstPts.get(i*2+1);
}
centerx /= 4;
centery /= 4;
for (int i = 0; i < 4; i++) {
double a = dstPts.get(i*2 );
double b = dstPts.get(i*2+1);
double dx = centerx - a;
double dy = centery - b;
dx = dx < 0 ? -1 : 0;
dy = dy < 0 ? -1 : 0;
tempPts.position(i).x((int)Math.round((a*scaleX + dx) * (1<<16)));
tempPts.position(i).y((int)Math.round((b*scaleY + dy) * (1<<16)));
}
cvFillConvexPoly(image, tempPts.position(0), 4, color, 8/*CV_AA*/, 16);
}
}
}
}
public static class ArraySettings extends BaseChildSettings {
int rows = 8, columns = 12;
double sizeX = 200, sizeY = 200, spacingX = 300, spacingY = 300;
boolean checkered = true;
public int getRows() {
return rows;
}
public void setRows(int rows) {
firePropertyChange("rows", this.rows, this.rows = rows);
}
public int getColumns() {
return columns;
}
public void setColumns(int columns) {
firePropertyChange("columns", this.columns, this.columns = columns);
}
public double getSizeX() {
return sizeX;
}
public void setSizeX(double sizeX) {
firePropertyChange("sizeX", this.sizeX, this.sizeX = sizeX);
}
public double getSizeY() {
return sizeY;
}
public void setSizeY(double sizeY) {
firePropertyChange("sizeY", this.sizeY, this.sizeY = sizeY);
}
public double getSpacingX() {
return spacingX;
}
public void setSpacingX(double spacingX) {
firePropertyChange("spacingX", this.spacingX, this.spacingX = spacingX);
}
public double getSpacingY() {
return spacingY;
}
public void setSpacingY(double spacingY) {
firePropertyChange("spacingY", this.spacingY, this.spacingY = spacingY);
}
public boolean isCheckered() {
return checkered;
}
public void setCheckered(boolean checkered) {
firePropertyChange("checkered", this.checkered, this.checkered = checkered);
}
}
public static Marker[][] createArray(ArraySettings settings) {
return createArray(settings, 0, 0);
}
public static Marker[][] createArray(ArraySettings settings, double marginx, double marginy) {
Marker[] markers = new Marker[settings.rows*settings.columns];
int id = 0;
for (int y = 0; y < settings.rows; y++) {
for (int x = 0; x < settings.columns; x++) {
double sx = settings.sizeX/2;
double sy = settings.sizeY/2;
double cx = x*settings.spacingX + sx + marginx;
double cy = y*settings.spacingY + sy + marginy;
markers[id] = new Marker(id, new double[] {
cx-sx, cy-sy, cx+sx, cy-sy, cx+sx, cy+sy, cx-sx, cy+sy }, 1);
id++;
}
}
if (!settings.checkered) {
return new Marker[][] { markers };
} else {
Marker[] markers1 = new Marker[markers.length/2];
Marker[] markers2 = new Marker[markers.length/2];
for (int i = 0; i < markers.length; i++) {
int x = i%settings.columns;
int y = i/settings.columns;
if (x%2==0 ^ y%2==0) {
markers2[i/2] = markers[i];
} else {
markers1[i/2] = markers[i];
}
}
return new Marker[][] { markers2, markers1 };
}
}
public static Marker[][] createArray(int rows, int columns, double sizeX, double sizeY,
double spacingX, double spacingY, boolean checkered, double marginx, double marginy) {
ArraySettings s = new ArraySettings();
s.rows = rows; s.columns = columns;
s.sizeX = sizeX; s.sizeY = sizeY;
s.spacingX = spacingX; s.spacingY = spacingY;
s.checkered = checkered;
return createArray(s, marginx, marginy);
}
public static void applyWarp(Marker[] markers, CvMat warp) {
CvMat pts = srcPts4x1.get();
for (Marker m : markers) {
cvPerspectiveTransform(pts.put(m.corners), pts, warp);
pts.get(m.corners);
}
}
@Override public String toString() {
String s = "[" + id + ": " +
"(" + corners[0] + ", " + corners[1] + ") " +
"(" + corners[2] + ", " + corners[3] + ") " +
"(" + corners[4] + ", " + corners[5] + ") " +
"(" + corners[6] + ", " + corners[7] + ")]";
return s;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy