chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:06:04 +08:00
commit 86c9b1c39f
7743 changed files with 3316339 additions and 0 deletions
@@ -0,0 +1,7 @@
bin/
gen/
build.xml
local.properties
proguard-project.txt
project.properties
default.properties
@@ -0,0 +1,25 @@
project(opencv_test_android)
set(OPENCV_ANDROID_TEST_DIR "${OpenCV_BINARY_DIR}/android_test" CACHE INTERNAL "")
file(REMOVE_RECURSE "${OPENCV_ANDROID_TEST_DIR}")
set(ANDROID_TESTS_SRC_DIRS
"'${CMAKE_CURRENT_SOURCE_DIR}/src', \
'${OpenCV_SOURCE_DIR}/modules/java/test/common_test/src', \
'${CMAKE_BINARY_DIR}/modules/java_bindings_generator/gen/test'" CACHE INTERNAL "")
set(ANDROID_TESTS_RES_DIR "'${OpenCV_SOURCE_DIR}/modules/java/test/common_test/res'" CACHE INTERNAL "")
list(APPEND TEST_PROJECT_FILES "CMakeLists.txt" "gradle.properties" "settings.gradle")
foreach(TEST_PROJECT_FILE ${TEST_PROJECT_FILES})
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/${TEST_PROJECT_FILE}" DESTINATION "${OPENCV_ANDROID_TEST_DIR}")
endforeach()
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests_module/AndroidManifest.xml" DESTINATION "${OPENCV_ANDROID_TEST_DIR}/tests_module")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tests_module/build.gradle.in" "${OPENCV_ANDROID_TEST_DIR}/tests_module/build.gradle" @ONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.gradle.in" "${OPENCV_ANDROID_TEST_DIR}/build.gradle" @ONLY)
file(COPY "${OpenCV_SOURCE_DIR}/platforms/android/gradle-wrapper/gradlew" DESTINATION "${OPENCV_ANDROID_TEST_DIR}")
file(COPY "${OpenCV_SOURCE_DIR}/platforms/android/gradle-wrapper/gradlew.bat" DESTINATION "${OPENCV_ANDROID_TEST_DIR}")
file(COPY "${OpenCV_SOURCE_DIR}/platforms/android/gradle-wrapper/gradle/wrapper/gradle-wrapper.jar" DESTINATION "${OPENCV_ANDROID_TEST_DIR}/gradle/wrapper")
configure_file("${OpenCV_SOURCE_DIR}/platforms/android/gradle-wrapper/gradle/wrapper/gradle-wrapper.properties.in" "${OPENCV_ANDROID_TEST_DIR}/gradle/wrapper/gradle-wrapper.properties" @ONLY)
@@ -0,0 +1,27 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:@ANDROID_GRADLE_PLUGIN_VERSION@'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:@KOTLIN_PLUGIN_VERSION@'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
@@ -0,0 +1,18 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2g
android.useAndroidX=true
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
@@ -0,0 +1,6 @@
rootProject.name = 'android_test'
include ':opencv'
project(':opencv').projectDir = new File('../opencv_android/opencv')
include ':tests_module'
@@ -0,0 +1,636 @@
package org.opencv.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.List;
import junit.framework.TestCase;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Point3;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.core.DMatch;
import org.opencv.core.KeyPoint;
import org.opencv.imgcodecs.Imgcodecs;
import android.util.Log;
import java.lang.reflect.Method;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
public class OpenCVTestCase extends TestCase {
public static class TestSkipException extends RuntimeException {
public TestSkipException() {}
}
//change to 'true' to unblock fail on fail("Not yet implemented")
public static final boolean passNYI = true;
protected static boolean isTestCaseEnabled = true;
protected static final String XFEATURES2D = "org.opencv.xfeatures2d.";
protected static final String DEFAULT_FACTORY = "create";
protected static final int matSize = 10;
protected static final double EPS = 0.001;
protected static final double weakEPS = 0.5;
private static final String TAG = "OpenCVTestCase";
protected Mat dst;
protected Mat truth;
protected Scalar colorBlack;
protected Scalar colorWhite;
// Naming notation: <channels info>_[depth]_[dimensions]_value
// examples: gray0 - single channel 8U 2d Mat filled with 0
// grayRnd - single channel 8U 2d Mat filled with random numbers
// gray0_32f_1d
// TODO: OpenCVTestCase refactorings
// - rename matrices
// - create methods gray0() and create src1 explicitly
// - create some masks
// - use truth member everywhere - remove truth from base class - each test
// fixture should use own truth filed
protected Mat gray0;
protected Mat gray1;
protected Mat gray2;
protected Mat gray3;
protected Mat gray9;
protected Mat gray127;
protected Mat gray128;
protected Mat gray255;
protected Mat grayRnd;
protected Mat gray_16u_256;
protected Mat gray_16s_1024;
protected Mat gray0_32f;
protected Mat gray1_32f;
protected Mat gray3_32f;
protected Mat gray9_32f;
protected Mat gray255_32f;
protected Mat grayE_32f;
protected Mat grayRnd_32f;
protected Mat gray0_32f_1d;
protected Mat gray0_64f;
protected Mat gray0_64f_1d;
protected Mat rgba0;
protected Mat rgba128;
protected Mat rgbLena;
protected Mat grayChess;
protected Mat gray255_32f_3d;
protected Mat v1;
protected Mat v2;
@Override
protected void setUp() throws Exception {
super.setUp();
dst = new Mat();
assertTrue(dst.empty());
truth = null;
colorBlack = new Scalar(0);
colorWhite = new Scalar(255, 255, 255);
gray0 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(0));
gray1 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(1));
gray2 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(2));
gray3 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(3));
gray9 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(9));
gray127 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(127));
gray128 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(128));
gray255 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(255));
grayRnd = new Mat(matSize, matSize, CvType.CV_8U);
Core.randu(grayRnd, 0, 256);
gray_16u_256 = new Mat(matSize, matSize, CvType.CV_16U, new Scalar(256));
gray_16s_1024 = new Mat(matSize, matSize, CvType.CV_16S, new Scalar(1024));
gray0_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(0.0));
gray1_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(1.0));
gray3_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(3.0));
gray9_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(9.0));
gray255_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(255.0));
grayE_32f = new Mat(matSize, matSize, CvType.CV_32F);
grayE_32f = Mat.eye(matSize, matSize, CvType.CV_32FC1);
grayRnd_32f = new Mat(matSize, matSize, CvType.CV_32F);
Core.randu(grayRnd_32f, 0, 256);
gray0_64f = new Mat(matSize, matSize, CvType.CV_64F, new Scalar(0.0));
gray0_32f_1d = new Mat(1, matSize, CvType.CV_32F, new Scalar(0.0));
gray0_64f_1d = new Mat(1, matSize, CvType.CV_64F, new Scalar(0.0));
rgba0 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(0));
rgba128 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(128));
rgbLena = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH);
grayChess = Imgcodecs.imread(OpenCVTestRunner.CHESS_PATH, Imgcodecs.IMREAD_GRAYSCALE);
gray255_32f_3d = new Mat(new int[]{matSize, matSize, matSize}, CvType.CV_32F, new Scalar(255.0));
v1 = new Mat(1, 3, CvType.CV_32F);
v1.put(0, 0, 1.0, 3.0, 2.0);
v2 = new Mat(1, 3, CvType.CV_32F);
v2.put(0, 0, 2.0, 1.0, 3.0);
}
@Override
protected void tearDown() throws Exception {
gray0.release();
gray1.release();
gray2.release();
gray3.release();
gray9.release();
gray127.release();
gray128.release();
gray255.release();
gray_16u_256.release();
gray_16s_1024.release();
grayRnd.release();
gray0_32f.release();
gray1_32f.release();
gray3_32f.release();
gray9_32f.release();
gray255_32f.release();
grayE_32f.release();
grayE_32f.release();
grayRnd_32f.release();
gray0_32f_1d.release();
gray0_64f.release();
gray0_64f_1d.release();
rgba0.release();
rgba128.release();
rgbLena.release();
grayChess.release();
gray255_32f_3d.release();
v1.release();
v2.release();
super.tearDown();
}
@Override
protected void runTest() throws Throwable {
// Do nothing if the precondition does not hold.
if (isTestCaseEnabled) {
try {
super.runTest();
} catch (TestSkipException ex) {
Log.w(TAG, "Test case \"" + this.getClass().getName() + "\" skipped!");
assertTrue(true);
}
} else {
Log.e(TAG, "Test case \"" + this.getClass().getName() + "\" disabled!");
}
}
public void runBare() throws Throwable {
Throwable exception = null;
try {
setUp();
} catch (TestSkipException ex) {
Log.w(TAG, "Test case \"" + this.getClass().getName() + "\" skipped!");
assertTrue(true);
return;
}
try {
runTest();
} catch (Throwable running) {
exception = running;
} finally {
try {
tearDown();
} catch (Throwable tearingDown) {
if (exception == null) exception = tearingDown;
}
}
if (exception != null) throw exception;
}
protected Mat getMat(int type, double... vals)
{
return new Mat(matSize, matSize, type, new Scalar(vals));
}
protected Mat makeMask(Mat m, double... vals)
{
m.submat(0, m.rows(), 0, m.cols() / 2).setTo(new Scalar(vals));
return m;
}
public static void fail(String msg) {
if(msg == "Not yet implemented" && passNYI)
return;
TestCase.fail(msg);
}
public static void assertGE(double v1, double v2) {
assertTrue("Failed: " + v1 + " >= " + v2, v1 >= v2);
}
public static <E extends Number> void assertListEquals(List<E> list1, List<E> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
if (!list1.isEmpty())
{
if (list1.get(0) instanceof Float || list1.get(0) instanceof Double)
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertEquals(list1.get(i), list2.get(i));
}
public static <E extends Number> void assertListEquals(List<E> list1, List<E> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertTrue(Math.abs(list1.get(i).doubleValue() - list2.get(i).doubleValue()) <= epsilon);
}
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertArrayEquals(short[] ar1, short[] ar2) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i]);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertArrayEquals(byte[] ar1, byte[] ar2) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i]);
}
public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i], epsilon);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertListMatEquals(List<Mat> list1, List<Mat> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertMatEqual(list1.get(i), list2.get(i), epsilon);
}
public static void assertListPointEquals(List<Point> list1, List<Point> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertPointEquals(list1.get(i), list2.get(i), epsilon);
}
public static void assertArrayPointsEquals(Point[] vp1, Point[] vp2, double epsilon) {
if (vp1.length != vp2.length) {
fail("Arrays have different sizes.");
}
for (int i = 0; i < vp1.length; i++)
assertPointEquals(vp1[i], vp2[i], epsilon);
}
public static void assertListPoint3Equals(List<Point3> list1, List<Point3> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertPoint3Equals(list1.get(i), list2.get(i), epsilon);
}
public static void assertListRectEquals(List<Rect> list1, List<Rect> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertRectEquals(list1.get(i), list2.get(i));
}
public static void assertListRotatedRectEquals(List<RotatedRect> list1, List<RotatedRect> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertRotatedRectEquals(list1.get(i), list2.get(i));
}
public static void assertRectEquals(Rect expected, Rect actual) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x);
assertEquals(msg, expected.y, actual.y);
assertEquals(msg, expected.width, actual.width);
assertEquals(msg, expected.height, actual.height);
}
public static void assertRotatedRectEquals(RotatedRect expected, RotatedRect actual) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.center.x, actual.center.x);
assertEquals(msg, expected.center.y, actual.center.y);
assertEquals(msg, expected.size.width, actual.size.width);
assertEquals(msg, expected.size.height, actual.size.height);
assertEquals(msg, expected.angle, actual.angle);
}
public static void assertMatEqual(Mat m1, Mat m2) {
compareMats(m1, m2, true);
}
public static void assertMatNotEqual(Mat m1, Mat m2) {
compareMats(m1, m2, false);
}
public static void assertMatEqual(Mat expected, Mat actual, double eps) {
compareMats(expected, actual, eps, true);
}
public static void assertMatNotEqual(Mat expected, Mat actual, double eps) {
compareMats(expected, actual, eps, false);
}
public static void assertKeyPointEqual(KeyPoint expected, KeyPoint actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertTrue(msg, Math.hypot(expected.pt.x - actual.pt.x, expected.pt.y - actual.pt.y) < eps);
assertTrue(msg, Math.abs(expected.size - actual.size) < eps);
assertTrue(msg, Math.abs(expected.angle - actual.angle) < eps);
assertTrue(msg, Math.abs(expected.response - actual.response) < eps);
assertEquals(msg, expected.octave, actual.octave);
assertEquals(msg, expected.class_id, actual.class_id);
}
public static void assertListKeyPointEquals(List<KeyPoint> expected, List<KeyPoint> actual, double epsilon) {
assertEquals(expected.size(), actual.size());
for (int i = 0; i < expected.size(); i++)
assertKeyPointEqual(expected.get(i), actual.get(i), epsilon);
}
public static void assertDMatchEqual(DMatch expected, DMatch actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.queryIdx, actual.queryIdx);
assertEquals(msg, expected.trainIdx, actual.trainIdx);
assertEquals(msg, expected.imgIdx, actual.imgIdx);
assertTrue(msg, Math.abs(expected.distance - actual.distance) < eps);
}
public static void assertScalarEqual(Scalar expected, Scalar actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertTrue(msg, Math.abs(expected.val[0] - actual.val[0]) < eps);
assertTrue(msg, Math.abs(expected.val[1] - actual.val[1]) < eps);
assertTrue(msg, Math.abs(expected.val[2] - actual.val[2]) < eps);
assertTrue(msg, Math.abs(expected.val[3] - actual.val[3]) < eps);
}
public static void assertArrayDMatchEquals(DMatch[] expected, DMatch[] actual, double epsilon) {
assertEquals(expected.length, actual.length);
for (int i = 0; i < expected.length; i++)
assertDMatchEqual(expected[i], actual[i], epsilon);
}
public static void assertListDMatchEquals(List<DMatch> expected, List<DMatch> actual, double epsilon) {
DMatch expectedArray[] = expected.toArray(new DMatch[0]);
DMatch actualArray[] = actual.toArray(new DMatch[0]);
assertArrayDMatchEquals(expectedArray, actualArray, epsilon);
}
public static void assertPointEquals(Point expected, Point actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x, eps);
assertEquals(msg, expected.y, actual.y, eps);
}
public static void assertSizeEquals(Size expected, Size actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.width, actual.width, eps);
assertEquals(msg, expected.height, actual.height, eps);
}
public static void assertPoint3Equals(Point3 expected, Point3 actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x, eps);
assertEquals(msg, expected.y, actual.y, eps);
assertEquals(msg, expected.z, actual.z, eps);
}
static private boolean dimensionsEqual(Mat expected, Mat actual) {
if (expected.dims() != actual.dims()) {
return false;
}
if (expected.dims() > 2) {
for (int i = 0; i < expected.dims(); i++) {
if (expected.size(i) != actual.size(i)) {
return false;
}
}
return true;
} else {
return expected.cols() == actual.cols() && expected.rows() == actual.rows();
}
}
static private void compareMats(Mat expected, Mat actual, boolean isEqualityMeasured) {
if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
}
if (expected.depth() == CvType.CV_32F || expected.depth() == CvType.CV_64F) {
if (isEqualityMeasured)
throw new UnsupportedOperationException(
"Floating-point Mats must not be checked for exact match. Use assertMatEqual(Mat expected, Mat actual, double eps) instead.");
else
throw new UnsupportedOperationException(
"Floating-point Mats must not be checked for exact match. Use assertMatNotEqual(Mat expected, Mat actual, double eps) instead.");
}
Mat diff = new Mat();
Core.absdiff(expected, actual, diff);
Mat reshaped = diff.reshape(1);
int mistakes = Core.countNonZero(reshaped);
reshaped.release();
diff.release();
if (isEqualityMeasured)
assertTrue("Mats are different in " + mistakes + " points", 0 == mistakes);
else
assertFalse("Mats are equal", 0 == mistakes);
}
static private void compareMats(Mat expected, Mat actual, double eps, boolean isEqualityMeasured) {
if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
}
Mat diff = new Mat();
Core.absdiff(expected, actual, diff);
double maxDiff = Core.norm(diff, Core.NORM_INF);
if (isEqualityMeasured)
assertTrue("Max difference between expected and actual Mats is "+ maxDiff + ", that bigger than " + eps,
maxDiff <= eps);
else
assertFalse("Max difference between expected and actual Mats is "+ maxDiff + ", that less than " + eps,
maxDiff <= eps);
}
protected static String readFile(String path) {
try {
BufferedReader br = new BufferedReader(new FileReader(path));
String line;
StringBuffer result = new StringBuffer();
while ((line = br.readLine()) != null) {
result.append(line);
result.append("\n");
}
return result.toString();
} catch (IOException e) {
OpenCVTestRunner.Log("Failed to read file \"" + path
+ "\". Exception is thrown: " + e);
return null;
}
}
protected static void writeFile(String path, String content) {
FileOutputStream stream = null;
try {
stream = new FileOutputStream(new File(path));
FileChannel fc = stream.getChannel();
fc.write(Charset.defaultCharset().encode(content));
} catch (IOException e) {
OpenCVTestRunner.Log("Failed to write file \"" + path
+ "\". Exception is thrown: " + e);
} finally {
if (stream != null)
try {
stream.close();
} catch (IOException e) {
OpenCVTestRunner.Log("Exception is thrown: " + e);
}
}
}
protected <T> T createClassInstance(String cname, String factoryName, Class cParams[], Object oValues[]) {
T instance = null;
assertFalse("Class name should not be empty", "".equals(cname));
String message="";
try {
Class algClass = getClassForName(cname);
Method factory = null;
if(cParams!=null && cParams.length>0) {
if(!"".equals(factoryName)) {
factory = algClass.getDeclaredMethod(factoryName, cParams);
instance = (T) factory.invoke(null, oValues);
}
else {
instance = (T) algClass.getConstructor(cParams).newInstance(oValues);
}
}
else {
if(!"".equals(factoryName)) {
factory = algClass.getDeclaredMethod(factoryName);
instance = (T) factory.invoke(null);
}
else {
instance = (T) algClass.getConstructor().newInstance();
}
}
}
catch(Exception ex) {
if (cname.startsWith(XFEATURES2D))
{
throw new TestSkipException();
}
message = TAG + " :: " + "could not instantiate " + cname + "! Exception: " + ex.getMessage();
}
assertNotNull(message, instance);
return instance;
}
protected <T> void setProperty(T instance, String propertyName, String propertyType, Object propertyValue) {
String message = "";
try {
String smethod = "set" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
Method setter = instance.getClass().getMethod(smethod, getClassForName(propertyType));
setter.invoke(instance, propertyValue);
}
catch(Exception ex) {
message = "Error when setting property [" + propertyName + "]: " + ex.getMessage();
}
assertTrue(message, "".equals(message));
}
protected Class getClassForName(String sclass) throws ClassNotFoundException{
if("int".equals(sclass))
return Integer.TYPE;
else if("long".equals(sclass))
return Long.TYPE;
else if("double".equals(sclass))
return Double.TYPE;
else if("float".equals(sclass))
return Float.TYPE;
else if("boolean".equals(sclass))
return Boolean.TYPE;
else if("char".equals(sclass))
return Character.TYPE;
else if("byte".equals(sclass))
return Byte.TYPE;
else if("short".equals(sclass))
return Short.TYPE;
else
return Class.forName(sclass);
}
}
@@ -0,0 +1,78 @@
package org.opencv.test;
import java.io.File;
import java.io.IOException;
import junit.framework.Assert;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import android.content.Context;
import android.util.Log;
import androidx.test.runner.AndroidJUnitRunner;
/**
* This only class is Android specific.
*/
public class OpenCVTestRunner extends AndroidJUnitRunner {
private static final long MANAGER_TIMEOUT = 3000;
public static String LENA_PATH;
public static String CHESS_PATH;
public static String LBPCASCADE_FRONTALFACE_PATH;
public static Context context;
private static String TAG = "opencv_test_java";
public static String getTempFileName(String extension)
{
File cache = context.getCacheDir();
if (!extension.startsWith("."))
extension = "." + extension;
try {
File tmp = File.createTempFile("OpenCV", extension, cache);
String path = tmp.getAbsolutePath();
tmp.delete();
return path;
} catch (IOException e) {
Log("Failed to get temp file name. Exception is thrown: " + e);
}
return null;
}
static public void Log(String message) {
Log.e(TAG, message);
}
static public void Log(Mat m) {
Log.e(TAG, m + "\n " + m.dump());
}
@Override
public void onStart() {
Assert.assertTrue(OpenCVLoader.initLocal());
context = getTargetContext();
Assert.assertNotNull("Context can't be 'null'", context);
LENA_PATH = Utils.exportResource(context, context.getResources().getIdentifier("lena", "drawable", context.getPackageName()));
CHESS_PATH = Utils.exportResource(context, context.getResources().getIdentifier("chessboard", "drawable", context.getPackageName()));
//LBPCASCADE_FRONTALFACE_PATH = Utils.exportResource(context, R.raw.lbpcascade_frontalface);
/*
* The original idea about test order randomization is from
* marek.defecinski blog.
*/
//List<TestCase> testCases = androidTestRunner.getTestCases();
//Collections.shuffle(testCases); //shuffle the tests order
super.onStart();
}
public static String getOutputFileName(String name)
{
return context.getExternalFilesDir(null).getAbsolutePath() + File.separatorChar + name;
}
}
@@ -0,0 +1,25 @@
package org.opencv.test.android
import org.opencv.core.CvType
import org.opencv.core.Mat
import org.opencv.core.times
import org.opencv.test.OpenCVTestCase
import kotlin.math.abs
class KotlinTest : OpenCVTestCase() {
fun testMatrixMultiplication() {
val m1 = Mat.ones(2, 3, CvType.CV_32F)
val m2 = Mat.ones(3, 2, CvType.CV_32F)
val m3 = m1.matMul(m2)
val m4 = m1 * m2
val value1 = floatArrayOf(3f)
m3.get(0, 1, value1)
val value2 = floatArrayOf(5f)
m4[0, 1, value2]
assertGE(0.001, abs(value1[0] - value2[0]).toDouble())
}
}
@@ -0,0 +1,225 @@
package org.opencv.test.android;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.test.OpenCVTestCase;
import org.opencv.test.OpenCVTestRunner;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.util.Log;
public class UtilsTest extends OpenCVTestCase {
private int[] testImgWH = new int[]{64, 48};
private byte[] testImgBgColor = new byte[]{1, 2, 3};
private int[] testImgRect = new int[] {15, 17, 25, 37};
private byte[] testImgRectColor = new byte[]{45, 15, 67};
private Mat createTestBGRImg() {
Mat img = new Mat(testImgWH[1], testImgWH[0], CvType.CV_8UC3,
new Scalar(testImgBgColor[2], testImgBgColor[1], testImgBgColor[0]));
byte[] color = new byte[]{testImgRectColor[2], testImgRectColor[1], testImgRectColor[0]};
for (int i = testImgRect[1]; i < testImgRect[3]; i++) {
for (int j = testImgRect[0]; j < testImgRect[2]; j++) {
img.put(i, j, color);
}
}
return img;
}
private Bitmap createTestBitmap() {
Bitmap img = Bitmap.createBitmap(testImgWH[0], testImgWH[1], Bitmap.Config.ARGB_8888);
img.eraseColor(Color.argb(255, testImgBgColor[0], testImgBgColor[1] ,testImgBgColor[2]));
for (int i = testImgRect[1]; i < testImgRect[3]; i++) {
for (int j = testImgRect[0]; j < testImgRect[2]; j++) {
img.setPixel(j, i, Color.argb(
255, testImgRectColor[0], testImgRectColor[1], testImgRectColor[2]));
}
}
return img;
}
public void testMatBitmapConversion() {
Mat mat = new Mat();
Imgproc.cvtColor(createTestBGRImg(), mat, Imgproc.COLOR_BGR2RGBA);
Bitmap bmp = createTestBitmap();
Bitmap convertedBmp = Bitmap.createBitmap(
Bitmap.createBitmap(testImgWH[0], testImgWH[1], Bitmap.Config.ARGB_8888));
Utils.matToBitmap(mat, convertedBmp);
assertTrue(bmp.sameAs(convertedBmp));
Mat convertedMat = new Mat();
Utils.bitmapToMat(bmp, convertedMat);
Mat diff = new Mat();
Core.absdiff(mat, convertedMat, diff);
Scalar channelsDiff = Core.sumElems(diff);
assertEquals(0.0, channelsDiff.val[0]);
assertEquals(0.0, channelsDiff.val[1]);
assertEquals(0.0, channelsDiff.val[2]);
assertEquals(0.0, channelsDiff.val[3]);
}
public void testBitmapToMat() {
BitmapFactory.Options opt16 = new BitmapFactory.Options();
opt16.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bmp16 = BitmapFactory.decodeFile(OpenCVTestRunner.LENA_PATH, opt16);
Mat m16 = new Mat();
Utils.bitmapToMat(bmp16, m16);
assertTrue(m16.rows() == 512 && m16.cols() == 512 && m16.type() == CvType.CV_8UC4);
/*BitmapFactory.Options opt32 = new BitmapFactory.Options();
opt32.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bmp32 = BitmapFactory.decodeFile(OpenCVTestRunner.LENA_PATH, opt32);*/
Bitmap bmp32 = bmp16.copy(Bitmap.Config.ARGB_8888, false);
Mat m32 = new Mat();
Utils.bitmapToMat(bmp32, m32);
assertTrue(m16.rows() == m32.rows() && m16.cols() == m32.cols() && m16.type() == m32.type());
double maxDiff = Core.norm(m16, m32, Core.NORM_INF);
Log.d("Bmp->Mat", "bmp16->Mat vs bmp32->Mat diff = " + maxDiff);
assertTrue(maxDiff <= 8 /* 8 == 2^8 / 2^5 */);
}
public void testExportResourceContextInt() {
fail("Not yet implemented");
}
public void testExportResourceContextIntString() {
fail("Not yet implemented");
}
public void testLoadResourceContextInt() {
fail("Not yet implemented");
}
public void testLoadResourceContextIntInt() {
fail("Not yet implemented");
}
public void testMatToBitmap() {
Mat imgBGR = Imgcodecs.imread( OpenCVTestRunner.LENA_PATH );
assertTrue(imgBGR != null && !imgBGR.empty() && imgBGR.channels() == 3);
Mat m16 = new Mat(imgBGR.rows(), imgBGR.cols(), CvType.CV_8UC4);
Mat m32 = new Mat(imgBGR.rows(), imgBGR.cols(), CvType.CV_8UC4);
Bitmap bmp16 = Bitmap.createBitmap(imgBGR.cols(), imgBGR.rows(), Bitmap.Config.RGB_565);
Bitmap bmp32 = Bitmap.createBitmap(imgBGR.cols(), imgBGR.rows(), Bitmap.Config.ARGB_8888);
double maxDiff;
Scalar s0 = new Scalar(0);
Scalar s255 = Scalar.all(255);
// RGBA
Mat imgRGBA = new Mat();
Imgproc.cvtColor(imgBGR, imgRGBA, Imgproc.COLOR_BGR2RGBA);
assertFalse(imgRGBA.empty() && imgRGBA.channels() == 4);
bmp16.eraseColor(Color.BLACK); m16.setTo(s0);
Utils.matToBitmap(imgRGBA, bmp16); Utils.bitmapToMat(bmp16, m16);
maxDiff = Core.norm(imgRGBA, m16, Core.NORM_INF);
Log.d("RGBA->bmp16->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff <= 8 /* 8 == 2^8 / 2^5 */);
bmp32.eraseColor(Color.WHITE); m32.setTo(s255);
Utils.matToBitmap(imgRGBA, bmp32); Utils.bitmapToMat(bmp32, m32);
maxDiff = Core.norm(imgRGBA, m32, Core.NORM_INF);
Log.d("RGBA->bmp32->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff == 0);
// RGB
Mat imgRGB = new Mat();
Imgproc.cvtColor(imgBGR, imgRGB, Imgproc.COLOR_BGR2RGB);
assertFalse(imgRGB.empty() && imgRGB.channels() == 3);
bmp16.eraseColor(Color.BLACK); m16.setTo(s0);
Utils.matToBitmap(imgRGB, bmp16); Utils.bitmapToMat(bmp16, m16);
maxDiff = Core.norm(imgRGBA, m16, Core.NORM_INF);
Log.d("RGB->bmp16->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff <= 8 /* 8 == 2^8 / 2^5 */);
bmp32.eraseColor(Color.WHITE); m32.setTo(s255);
Utils.matToBitmap(imgRGB, bmp32); Utils.bitmapToMat(bmp32, m32);
maxDiff = Core.norm(imgRGBA, m32, Core.NORM_INF);
Log.d("RGB->bmp32->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff == 0);
// Gray
Mat imgGray = new Mat();
Imgproc.cvtColor(imgBGR, imgGray, Imgproc.COLOR_BGR2GRAY);
assertFalse(imgGray.empty() && imgGray.channels() == 1);
Mat tmp = new Mat();
bmp16.eraseColor(Color.BLACK); m16.setTo(s0);
Utils.matToBitmap(imgGray, bmp16); Utils.bitmapToMat(bmp16, m16);
Core.extractChannel(m16, tmp, 0);
maxDiff = Core.norm(imgGray, tmp, Core.NORM_INF);
Log.d("Gray->bmp16->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff <= 8 /* 8 == 2^8 / 2^5 */);
bmp32.eraseColor(Color.WHITE); m32.setTo(s255);
Utils.matToBitmap(imgGray, bmp32); Utils.bitmapToMat(bmp32, m32);
tmp.setTo(s0);
Core.extractChannel(m32, tmp, 0);
maxDiff = Core.norm(imgGray, tmp, Core.NORM_INF);
Log.d("Gray->bmp32->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff == 0);
}
public void testAlphaPremultiplication() {
final int size = 256;
Bitmap bmp = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Mat mOrig = new Mat(size, size, CvType.CV_8UC4);
Mat mUnPre = new Mat(size, size, CvType.CV_8UC4);
for(int y=0; y<size; y++) {
int a = y;
for(int x=0; x<size; x++) {
int color = Color.argb(a, 0, x, y);
bmp.setPixel(x, y, color);
mOrig.put(y, x, Color.red(color), Color.green(color), Color.blue(color), Color.alpha(color));
int colorUnPre = bmp.getPixel(x, y);
mUnPre.put(y, x, Color.red(colorUnPre), Color.green(colorUnPre), Color.blue(colorUnPre), Color.alpha(colorUnPre));
}
}
// Bitmap -> Mat
Mat m1 = new Mat();
Mat m2 = new Mat();
Utils.bitmapToMat(bmp, m1, false);
Imgproc.cvtColor(mOrig, m2, Imgproc.COLOR_RGBA2mRGBA);
assertMatEqual(m1, m2, 1.1);
Utils.bitmapToMat(bmp, m1, true);
assertMatEqual(m1, mUnPre, 1.1);
// Mat -> Bitmap
Bitmap bmp1 = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mOrig, bmp1, true);
Utils.bitmapToMat(bmp1, m1, true);
//assertMatEqual(m1, mUnPre, 1.1);
Mat diff = new Mat();
Core.absdiff(m1, mUnPre, diff);
int numDiff = Core.countNonZero(diff.reshape(1));
assertTrue(numDiff < size * 4);
}
}
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.opencv.samples.tutorial1"
>
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
</application>
</manifest>
@@ -0,0 +1,36 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
namespace 'org.opencv.tests'
compileSdkVersion @ANDROID_COMPILE_SDK_VERSION@
defaultConfig {
applicationId "org.opencv.tests"
minSdkVersion @ANDROID_MIN_SDK_VERSION@
targetSdkVersion @ANDROID_TARGET_SDK_VERSION@
versionCode 301
versionName "3.01"
testInstrumentationRunner "org.opencv.test.OpenCVTestRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
androidTest {
java.srcDirs = [@ANDROID_TESTS_SRC_DIRS@]
}
main {
manifest.srcFile 'AndroidManifest.xml'
res.srcDirs = [@ANDROID_TESTS_RES_DIR@]
}
}
}
dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation project(':opencv')
}