This commit is contained in:
ori agranat
2020-02-28 00:13:18 +02:00
119 changed files with 628 additions and 449 deletions

View File

@@ -3915,7 +3915,8 @@
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
"dev": true
"dev": true,
"optional": true
},
"coa": {
"version": "2.0.2",
@@ -6308,7 +6309,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@@ -6517,7 +6519,8 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.9.0",
@@ -6542,6 +6545,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -6730,7 +6734,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -6786,6 +6791,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -6829,12 +6835,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
@@ -10639,7 +10647,8 @@
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
"integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
"dev": true
"dev": true,
"optional": true
},
"rx-lite-aggregates": {
"version": "4.0.8",
@@ -14743,7 +14752,8 @@
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true
"bundled": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@@ -14780,7 +14790,8 @@
},
"code-point-at": {
"version": "1.1.0",
"bundled": true
"bundled": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
@@ -14789,7 +14800,8 @@
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true
"bundled": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -14892,7 +14904,8 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true
"bundled": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@@ -14902,6 +14915,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -14921,11 +14935,13 @@
},
"minimist": {
"version": "0.0.8",
"bundled": true
"bundled": true,
"optional": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -14942,6 +14958,7 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -15014,7 +15031,8 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true
"bundled": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -15024,6 +15042,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@@ -15099,7 +15118,8 @@
},
"safe-buffer": {
"version": "5.1.1",
"bundled": true
"bundled": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -15129,6 +15149,7 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -15146,6 +15167,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -15184,11 +15206,13 @@
},
"wrappy": {
"version": "1.0.2",
"bundled": true
"bundled": true,
"optional": true
},
"yallist": {
"version": "3.0.2",
"bundled": true
"bundled": true,
"optional": true
}
}
},

View File

@@ -76,7 +76,7 @@
// move the rotation point to the center of the rect
this.ctx.translate(y + this.targetWidth / 2, x + this.targetHeight / 2); // wpi lib makes x forward and back and y left to right
// rotate the rect
this.ctx.rotate(target.rotation.radians);
this.ctx.rotate(target.rotation.radians * -1);
// draw the rect on the transformed context
// Note: after transforming [0,0] is visually [x,y]

View File

@@ -12,6 +12,7 @@
</v-btn>
</v-col>
</v-row>
<CVslider name="Contour simplification" v-model="value.accuracy" :min="0" :max="100" @input="handleData('accuracy')"/>
<v-row>
<v-col>
<mini-map class="miniMapClass" :targets="targets" :horizontal-f-o-v="horizontalFOV"/>
@@ -29,9 +30,10 @@
</template>
<script>
import Papa from 'papaparse';
import miniMap from '../../components/3D/MiniMap';
import CVswitch from '../../components/cv-switch';
import Papa from 'papaparse';
import CVslider from '../../components/cv-slider'
import FRCtargetsConfig from '../../assets/FRCtargets'
export default {
@@ -39,6 +41,7 @@
props: ['value'],
components: {
CVswitch,
CVslider,
miniMap
},
data() {

View File

@@ -265,8 +265,10 @@
this.$store.commit('cameraSettings', value);
}
},
pipeline() {
return this.$store.state.pipeline
pipeline: {
get() {
return this.$store.state.pipeline;
}
}
}
}

View File

@@ -104,9 +104,9 @@
computed: {
fileUploadText() {
if (this.file !== undefined) {
return "Install and update"
return "Update and run at startup"
} else {
return "Install current version"
return "Run current version at startup"
}
},
isDisabled() {

View File

@@ -11,6 +11,7 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.6" level="project" />
<orderEntry type="library" name="Maven: io.javalin:javalin:3.7.0" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.61" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.3.61" level="project" />
@@ -36,6 +37,7 @@
<orderEntry type="library" name="Maven: org.json:json:20190722" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-nop:1.7.26" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-math3:3.6.1" level="project" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.6" level="project" />
<orderEntry type="library" name="Maven: org.msgpack:msgpack-core:0.8.18" level="project" />
<orderEntry type="library" name="Maven: org.msgpack:jackson-dataformat-msgpack:0.8.18" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.9" level="project" />

View File

@@ -6,7 +6,7 @@
<groupId>org.chameleon-vision.main</groupId>
<artifactId>chameleon-vision</artifactId>
<version>2.3-RELEASE</version>
<version>2.3.1-RELEASE</version>
<build>
<plugins>
<!--setup for java jdk 12-->
@@ -86,6 +86,11 @@
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>

View File

@@ -12,6 +12,7 @@ public class CameraJsonConfig {
public final String name;
public final String nickname;
public final int videomode;
public final double tilt;
public final StreamDivisor streamDivisor;
@JsonCreator
@@ -21,13 +22,15 @@ public class CameraJsonConfig {
@JsonProperty("name") String name,
@JsonProperty("nickname") String nickname,
@JsonProperty("videomode") int videomode,
@JsonProperty("streamDivisor") StreamDivisor streamDivisor) {
@JsonProperty("streamDivisor") StreamDivisor streamDivisor,
@JsonProperty("tilt") double tilt) {
this.fov = fov;
this.path = path;
this.name = name;
this.nickname = nickname;
this.videomode = videomode;
this.streamDivisor = streamDivisor;
this.tilt = tilt;
}
public CameraJsonConfig(String path, String name) {
@@ -37,12 +40,14 @@ public class CameraJsonConfig {
this.nickname = name;
this.videomode = 0;
this.streamDivisor = StreamDivisor.NONE;
this.tilt = 0;
}
public static CameraJsonConfig fromVisionProcess(VisionProcess process) {
USBCaptureProperties camProps = process.getCamera().getProperties();
int videomode = camProps.getCurrentVideoModeIndex();
StreamDivisor streamDivisor = process.cameraStreamer.getDivisor();
return new CameraJsonConfig(camProps.getFOV(), camProps.path, camProps.name, camProps.getNickname(), videomode, streamDivisor);
double tilt = process.getCamera().getProperties().getTilt().getDegrees();
return new CameraJsonConfig(camProps.getFOV(), camProps.path, camProps.name, camProps.getNickname(), videomode, streamDivisor, tilt);
}
}

View File

@@ -74,6 +74,7 @@ public class StandardCVPipelineSettingsDeserializer extends BaseDeserializer<Sta
pipeline.is3D = getBoolean("is3D", pipeline.is3D);
pipeline.targetCornerMat = getMatOfPoint3f("targetCornerMat", pipeline.targetCornerMat);
pipeline.accuracy = getDouble("accuracy", pipeline.accuracy.doubleValue());
return pipeline;
}

View File

@@ -77,6 +77,7 @@ public class StandardCVPipelineSettingsSerializer extends BaseSerializer<Standar
gen.writeBooleanField("is3D", pipeline.is3D);
writeMatOfPoint3f("targetCornerMat", pipeline.targetCornerMat);
gen.writeNumberField("accuracy", pipeline.accuracy.doubleValue());
gen.writeEndObject();
}
}

View File

@@ -1,73 +1,102 @@
package com.chameleonvision.network;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class LinuxNetworking extends SysNetworking {
private static final String PATH = "/etc/dhcpcd.conf";
@Override
public boolean setDHCP() {
String[] clearArgs = { "addr", "flush", "dev", networkInterface.name };
try {
int clearRetCode = shell.execute("ip", clearArgs);
int dhcpRetCode = shell.execute("dhclient", networkInterface.name);
return clearRetCode == 0 && dhcpRetCode == 0;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean setDHCP() {
File dhcpConf = new File(PATH);
if (dhcpConf.exists()) {
try {
List<String> lines = FileUtils.readLines(dhcpConf, StandardCharsets.UTF_8);
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
if (line.startsWith("interface " + networkInterface.name)) {
lines.remove(i);
for (int j = i; j < lines.size(); j++) {
String subInterface = lines.get(j);
if (subInterface.contains("static ip_address") || subInterface.contains("static routers")) {
lines.remove(j);
j--;
}
if (subInterface.contains("interface")) {
break;
}
}
FileUtils.writeLines(dhcpConf, lines);
return true;
}
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
@Override
public boolean setHostname(String newHostname) {
String[] setHostnameArgs = { "set-hostname", newHostname };
try {
var setHostnameRetCode = shell.execute("hostnamectl", setHostnameArgs);
return setHostnameRetCode == 0;
} catch(Exception e) {
e.printStackTrace();
return false;
}
}
} else {
System.err.println("dhcpcd5 is not installed cant set ip");
return false;
}
return true;
}
@Override
public boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) {
try {
String[] clearArgs = { "addr", "flush", "dev", networkInterface.name };
String[] setIPArgs = { "addr", "add", String.format("%s/%s", ipAddress, netmask), "broadcast", broadcast, "dev", networkInterface.name };
String[] setGatewayArgs = { "route", "replace", "default", "via", gateway, "dev", networkInterface.name };
@Override
public boolean setHostname(String newHostname) {
String[] setHostnameArgs = {"set-hostname", newHostname};
try {
var setHostnameRetCode = shell.execute("hostnamectl", setHostnameArgs);
return setHostnameRetCode == 0;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
int clearRetCode = shell.execute("ip", clearArgs);
int setIPRetCode = shell.execute("ip", setIPArgs);
int setGatewayRetCode = shell.execute("ip", setGatewayArgs);
@Override
public boolean setStatic(String ipAddress, String netmask, String gateway) {
setDHCP(); // clean up old static interface
File dhcpConf = new File(PATH);
try {
List<String> lines = FileUtils.readLines(dhcpConf, StandardCharsets.UTF_8);
lines.add("interface " + networkInterface.name);
InetAddress iNetMask = InetAddress.getByName(netmask);
int prefix = NetmaskToCIDR.convertNetmaskToCIDR(iNetMask);
lines.add("static ip_address " + ipAddress + "/" + prefix);
lines.add("static routers " + gateway);
FileUtils.writeLines(dhcpConf, lines);
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
return clearRetCode == 0 && setIPRetCode == 0 && setGatewayRetCode == 0;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
@Override
public List<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException {
List<java.net.NetworkInterface> netInterfaces;
try {
netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
} catch (SocketException e) {
return null;
}
@Override
public List<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException {
List<java.net.NetworkInterface> netInterfaces;
try {
netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
} catch (SocketException e) {
return null;
}
List<java.net.NetworkInterface> goodInterfaces = new ArrayList<>();
List<java.net.NetworkInterface> goodInterfaces = new ArrayList<>();
for (var netInterface : netInterfaces) {
if (netInterface.getDisplayName().contains("lo")) continue;
if (!netInterface.isUp()) continue;
goodInterfaces.add(netInterface);
}
return goodInterfaces;
for (var netInterface : netInterfaces) {
if (netInterface.getDisplayName().contains("lo")) continue;
if (!netInterface.isUp()) continue;
goodInterfaces.add(netInterface);
}
return goodInterfaces;
}
}
}

View File

@@ -0,0 +1,29 @@
package com.chameleonvision.network;
import java.net.InetAddress;
public class NetmaskToCIDR {
//code belongs to https://stackoverflow.com/questions/19531411/calculate-cidr-from-a-given-netmask-java
public static int convertNetmaskToCIDR(InetAddress netmask) {
byte[] netmaskBytes = netmask.getAddress();
int cidr = 0;
boolean zero = false;
for (byte b : netmaskBytes) {
int mask = 0x80;
for (int i = 0; i < 8; i++) {
int result = b & mask;
if (result == 0) {
zero = true;
} else if (zero) {
throw new IllegalArgumentException("Invalid netmask.");
} else {
cidr++;
}
mask >>>= 1;
}
}
return cidr;
}
}

View File

@@ -9,44 +9,45 @@ import java.util.ArrayList;
import java.util.List;
public class NetworkManager {
private NetworkManager() {}
private NetworkManager() {
}
private static SysNetworking networking;
private static boolean isManaged = false;
private static SysNetworking networking;
private static boolean isManaged = false;
public static void initialize(boolean manage) {
isManaged = manage;
if (!isManaged) {
return;
}
public static void initialize(boolean manage) {
isManaged = manage;
if (!isManaged) {
return;
}
Platform platform = Platform.CurrentPlatform;
Platform platform = Platform.CurrentPlatform;
if (platform.isLinux()) {
networking = new LinuxNetworking();
} else if (platform.isWindows()) {
if (platform.isLinux()) {
networking = new LinuxNetworking();
} else if (platform.isWindows()) {
// networking = new WindowsNetworking();
System.out.println("Windows networking is not yet supported. Running unmanaged.");
return;
}
}
if (networking == null) {
throw new RuntimeException("Failed to detect platform!");
}
if (networking == null) {
throw new RuntimeException("Failed to detect platform!");
}
List<java.net.NetworkInterface> interfaces = new ArrayList<>();
List<NetworkInterface> goodInterfaces = new ArrayList<>();
List<java.net.NetworkInterface> interfaces = new ArrayList<>();
List<NetworkInterface> goodInterfaces = new ArrayList<>();
try {
interfaces = networking.getNetworkInterfaces();
} catch (SocketException e) {
e.printStackTrace();
}
try {
interfaces = networking.getNetworkInterfaces();
} catch (SocketException e) {
e.printStackTrace();
}
var teamBytes = NetworkManager.GetTeamNumberIPBytes(ConfigManager.settings.teamNumber);
if (interfaces.size() > 0) {
for (var inetface : interfaces) {
for (var inetface : interfaces) {
for (var inetfaceAddr : inetface.getInterfaceAddresses()) {
var rawAddr = inetfaceAddr.getAddress().getAddress();
if (rawAddr.length > 4) continue;
@@ -54,74 +55,53 @@ public class NetworkManager {
goodInterfaces.add(new NetworkInterface(inetface, inetfaceAddr));
}
}
}
}
if (goodInterfaces.size() == 0) {
isManaged = false;
System.err.println("No valid network interfaces found! Staying unmanaged.");
return;
}
if (goodInterfaces.size() == 0) {
isManaged = false;
System.err.println("No valid network interfaces found! Staying unmanaged.");
return;
}
NetworkInterface botInterface = goodInterfaces.get(0);
networking.setNetworkInterface(botInterface);
} else {
isManaged = false;
System.err.println("No valid network interfaces found! Staying unmanaged.");
return;
}
if(!loadFromGeneralSettings()) {
isManaged = false;
System.err.println("Failed to load network settings. Staying unmanaged!");
}
}
private static byte[] GetTeamNumberIPBytes(int teamNumber) {
return new byte[]{(byte) (teamNumber / 100), (byte) (teamNumber % 100)};
}
private static boolean loadFromGeneralSettings() {
if (!isManaged) {
return true;
}
var genSettings = ConfigManager.settings;
boolean isStatic = genSettings.connectionType.equals(NetworkIPMode.STATIC);
if (isStatic) {
var splitIPAddr = genSettings.ip.split("\\.");
splitIPAddr[3] = "255";
var broadcast = String.join(".", splitIPAddr);
if (!setStatic(genSettings.ip, genSettings.netmask, genSettings.gateway, broadcast)) {
return false;
}
} else {
if (!setDHCP()) {
return false;
}
}
return setHostname(genSettings.hostname);
}
private static boolean setDHCP() {
if (!isManaged) {
return true;
}
return networking.setDHCP();
NetworkInterface botInterface = goodInterfaces.get(0);
networking.setNetworkInterface(botInterface);
} else {
isManaged = false;
System.err.println("No valid network interfaces found! Staying unmanaged.");
}
}
private static boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) {
if (!isManaged) {
return true;
}
return networking.setStatic(ipAddress, netmask, gateway, broadcast);
private static byte[] GetTeamNumberIPBytes(int teamNumber) {
return new byte[]{(byte) (teamNumber / 100), (byte) (teamNumber % 100)};
}
private static boolean setHostname(String hostname) {
if (!isManaged) {
return true;
}
return networking.setHostname(hostname);
private static boolean setDHCP() {
if (!isManaged) {
return true;
}
return networking.setDHCP();
}
private static boolean setStatic(String ipAddress, String netmask, String gateway) {
if (!isManaged) {
return true;
}
return networking.setStatic(ipAddress, netmask, gateway);
}
public static boolean setHostname(String hostname) {
if (!isManaged) {
return true;
}
return networking.setHostname(hostname);
}
public static boolean setNetwork(boolean isStatic, String ip, String netmask, String gateway) {
if (isStatic) {
return setStatic(ip, netmask, gateway);
} else {
return setDHCP();
}
}
}

View File

@@ -30,7 +30,7 @@ public abstract class SysNetworking {
}
public abstract boolean setDHCP();
public abstract boolean setHostname(String hostname);
public abstract boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast);
public abstract boolean setStatic(String ipAddress, String netmask, String gateway);
public abstract List<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException;
}

View File

@@ -32,7 +32,7 @@ public class WindowsNetworking extends SysNetworking {
}
@Override
public boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) {
public boolean setStatic(String ipAddress, String netmask, String gateway) {
return false;
}

View File

@@ -4,6 +4,7 @@ import edu.wpi.cscore.VideoMode;
import org.opencv.core.Scalar;
import java.awt.*;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
@@ -17,8 +18,8 @@ public class Helpers {
"\n" +
"[Service]\n" +
"ExecStart=/usr/bin/java -jar %s \n" +
"StandardOutput=file:/var/log/something.out.txt\n" +
"StandardError=file:/var/log/something.err.txt\n" +
"StandardOutput=file:/var/log/chameleon.out.txt\n" +
"StandardError=file:/var/log/chameleon.err.txt\n" +
"Type=simple\n" +
"WorkingDirectory=/usr/local/bin\n" +
"\n" +
@@ -44,7 +45,11 @@ public class Helpers {
public static void setService(Path filePath) throws IOException, InterruptedException {
String newService = String.format(kServiceString, filePath.toString());
Writer writer = new FileWriter(kServicePath, false);
File file = new File(kServicePath);
if (file.exists()) {
file.delete();
}
Writer writer = new FileWriter(file, false);
writer.write(newService);
writer.close();
Process p = Runtime.getRuntime().exec("systemctl enable chameleonVision.service");

View File

@@ -3,10 +3,8 @@ package com.chameleonvision.util;
import java.io.File;
import java.net.URISyntaxException;
public class ProgramDirectoryUtilities
{
private static String getJarName()
{
public class ProgramDirectoryUtilities {
private static String getJarName() {
return new File(ProgramDirectoryUtilities.class.getProtectionDomain()
.getCodeSource()
.getLocation()
@@ -14,33 +12,23 @@ public class ProgramDirectoryUtilities
.getName();
}
private static boolean runningFromJAR()
{
private static boolean runningFromJAR() {
String jarName = getJarName();
return jarName.contains(".jar");
}
public static String getProgramDirectory()
{
if (runningFromJAR())
{
if (Platform.isRaspberryPi()) {
return "/boot/chameleon-vision";
}
public static String getProgramDirectory() {
if (runningFromJAR()) {
return getCurrentJARDirectory();
} else
{
} else {
return System.getProperty("user.dir");
}
}
private static String getCurrentJARDirectory()
{
try
{
private static String getCurrentJARDirectory() {
try {
return new File(ProgramDirectoryUtilities.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParent();
} catch (URISyntaxException exception)
{
} catch (URISyntaxException exception) {
exception.printStackTrace();
}

View File

@@ -54,6 +54,7 @@ public class USBCameraCapture implements CameraCapture {
}
public void addCalibrationData(CameraCalibrationConfig newConfig) {
calibrationList.removeIf(c -> newConfig.resolution.height == c.resolution.height && newConfig.resolution.width == c.resolution.width);
calibrationList.add(newConfig);
}
@@ -77,6 +78,7 @@ public class USBCameraCapture implements CameraCapture {
// TODO: Why multiply by 1000 here?
Mat tempMat = new Mat();
deltaTime = cvSink.grabFrame(tempMat) * 1000L;
// tempMat = Imgcodecs.imread("C:\\Users\\imadu\\Documents\\GitHub\\chameleon-vision\\chameleon-server\\testimages\\2020\\image.png");
tempMat.copyTo(imageBuffer);
tempMat.release();
return Pair.of(imageBuffer, deltaTime);

View File

@@ -45,6 +45,7 @@ public class USBCaptureProperties extends CaptureProperties {
FOV = config.fov;
name = config.name;
path = config.path;
setTilt(Rotation2d.fromDegrees(config.tilt));
nickname = config.nickname;
this.baseCamera = baseCamera;

View File

@@ -3,6 +3,8 @@ package com.chameleonvision.vision.pipeline;
import com.chameleonvision.Exceptions.DuplicatedKeyException;
import com.chameleonvision.config.CameraConfig;
import com.chameleonvision.config.ConfigManager;
import com.chameleonvision.scripting.ScriptEventType;
import com.chameleonvision.scripting.ScriptManager;
import com.chameleonvision.vision.VisionManager;
import com.chameleonvision.vision.VisionProcess;
import com.chameleonvision.vision.pipeline.impl.Calibrate3dPipeline;
@@ -124,6 +126,7 @@ public class PipelineManager {
CVPipeline newPipeline = null;
if (index == DRIVERMODE_INDEX) {
ScriptManager.queueEvent(ScriptEventType.kLEDOff);
newPipeline = driverModePipeline;
// if we're changing into driver mode, try to set the nt entry to true
@@ -138,6 +141,7 @@ public class PipelineManager {
// if we're switching out of driver mode, try to set the nt entry to false
parentProcess.setDriverModeEntry(false);
ScriptManager.queueEvent(ScriptEventType.kLEDOn);
}
else
{

View File

@@ -144,8 +144,8 @@ public class Calibrate3dPipeline extends CVPipeline<DriverVisionPipeline.DriverP
VisionManager.getCurrentUIVisionProcess().addCalibration(cal);
try {
System.out.printf("CALIBRATION SUCCESS! camMatrix: \n%s\ndistortionCoeffs:\n%s\n",
new ObjectMapper().writeValueAsString(cal.cameraMatrix), new ObjectMapper().writeValueAsString(cal.distortionCoeffs));
System.out.printf("CALIBRATION SUCCESS (with accuracy %s)! camMatrix: \n%s\ndistortionCoeffs:\n%s\n",
calibrationAccuracy, new ObjectMapper().writeValueAsString(cal.cameraMatrix), new ObjectMapper().writeValueAsString(cal.distortionCoeffs));
} catch (JsonProcessingException e) {
e.printStackTrace();
}

View File

@@ -200,7 +200,7 @@ public class StandardCVPipeline extends CVPipeline<StandardCVPipelineResult, Sta
if (settings.is3D) {
// once we've sorted our targets, perform solvePNP. The number of "best targets" is limited by the above pipe
Pair<List<TrackedTarget>, Long> solvePNPResult = solvePNPPipe.run(Pair.of(collect2dTargetsResult.getLeft(), hsvResult.getLeft()));
Pair<List<TrackedTarget>, Long> solvePNPResult = solvePNPPipe.run(Pair.of(collect2dTargetsResult.getLeft(), rotateFlipResult.getLeft()));
totalPipelineTimeNanos += solvePNPResult.getRight();
Pair<Mat, Long> draw3dContoursResult = drawSolvePNPPipe.run(Pair.of(outputMatResult.getLeft(), solvePNPResult.getLeft()));

View File

@@ -33,6 +33,7 @@ public class StandardCVPipelineSettings extends CVPipelineSettings {
// 3d stuff
public MatOfPoint3f targetCornerMat = new MatOfPoint3f();
public Number accuracy = 5;
private static MatOfPoint3f hexTargetMat = new MatOfPoint3f();
static {

View File

@@ -34,7 +34,7 @@ public class DrawSolvePNPPipe implements Pipe<Pair<Mat, List<StandardCVPipeline.
private void setBox(MatOfPoint3f mat) {
boxCornerMat.release();
var list = mat.toList();
var auxList = list.stream().map(it -> new Point3(it.x, it.y, it.z - 6)).collect(Collectors.toList());
var auxList = list.stream().map(it -> new Point3(it.x, it.y, it.z + 6)).collect(Collectors.toList());
var finalList = new ArrayList<>(list);
finalList.addAll(auxList);
boxCornerMat.fromList(finalList);

View File

@@ -4,6 +4,8 @@ import com.chameleonvision.config.CameraCalibrationConfig;
import com.chameleonvision.vision.pipeline.Pipe;
import com.chameleonvision.vision.pipeline.impl.StandardCVPipeline;
import com.chameleonvision.vision.pipeline.impl.StandardCVPipelineSettings;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.wpilibj.geometry.Pose2d;
import edu.wpi.first.wpilibj.geometry.Rotation2d;
import edu.wpi.first.wpilibj.geometry.Translation2d;
@@ -33,6 +35,10 @@ public class SolvePNPPipe implements Pipe<Pair<List<StandardCVPipeline.TrackedTa
Comparator<Point> verticalComparator = Comparator.comparingDouble(point -> point.y);
private double distanceDivisor = 1.0;
Mat scaledTvec = new Mat();
MatOfPoint2f boundingBoxResultMat = new MatOfPoint2f();
MatOfPoint2f polyOutput = new MatOfPoint2f();
private Mat greyImg = new Mat();
private double accuracyPercentage = 0.2;
public SolvePNPPipe(StandardCVPipelineSettings settings, CameraCalibrationConfig calibration, Rotation2d tilt) {
super();
@@ -83,6 +89,7 @@ public class SolvePNPPipe implements Pipe<Pair<List<StandardCVPipeline.TrackedTa
// TODO add proper year differentiation
tilt_angle = tilt.getRadians();
this.objPointsMat = settings.targetCornerMat;
this.accuracyPercentage = settings.accuracy.doubleValue();
}
private void setCameraCoeffs(CameraCalibrationConfig settings) {
@@ -105,10 +112,25 @@ public class SolvePNPPipe implements Pipe<Pair<List<StandardCVPipeline.TrackedTa
public Pair<List<StandardCVPipeline.TrackedTarget>, Long> run(Pair<List<StandardCVPipeline.TrackedTarget>, Mat> imageTargetPair) {
long processStartNanos = System.nanoTime();
var targets = imageTargetPair.getLeft();
var image = imageTargetPair.getRight();
Imgproc.cvtColor(image, greyImg, Imgproc.COLOR_BGR2GRAY);
poseList.clear();
for(var target: targets) {
var corners = find2020VisionTarget(target);//, imageTargetPair.getRight()); //find2020VisionTarget(target);// (target.leftRightDualTargetPair != null) ? findCorner2019(target) : findBoundingBoxCorners(target);
MatOfPoint2f corners;
if(target.leftRightRotatedRect == null) {
corners = find2020VisionTarget(target, accuracyPercentage);//, imageTargetPair.getRight()); //find2020VisionTarget(target);// (target.leftRightDualTargetPair != null) ? findCorner2019(target) : findBoundingBoxCorners(target);
} else {
corners = findCorner2019(target);
}
// var corners = findCorner2019(target);
if(corners == null) continue;
// // use best features to track
// corners = refineCornersByBestTrack(corners, greyImg, target);
// refine the estimate
// corners = refineCornerEstimateSubPix(corners, greyImg);
var pose = calculatePose(corners, target);
if(pose != null) poseList.add(pose);
}
@@ -145,38 +167,34 @@ public class SolvePNPPipe implements Pipe<Pair<List<StandardCVPipeline.TrackedTa
return FastMath.sqrt(FastMath.pow(a.x - b.x, 2) + FastMath.pow(a.y - b.y, 2));
}
MatOfInt tempInt = new MatOfInt();
MatOfPoint2f tempMat2f = new MatOfPoint2f();
MatOfPoint tempMatOfPoint = new MatOfPoint();
/**
* Find the target using the outermost tape corners and a 2020 target.
* @param target the target.
* @return The four outermost tape corners.
*/
private MatOfPoint2f find2020VisionTarget(StandardCVPipeline.TrackedTarget target) {
private MatOfPoint2f find2020VisionTarget(StandardCVPipeline.TrackedTarget target, double accuracyPercentage) {
if(target.rawContour.cols() < 1) return null;
var centroid = target.minAreaRect.center;
Comparator<Point> distanceProvider = Comparator.comparingDouble((Point point) -> FastMath.sqrt(FastMath.pow(centroid.x - point.x, 2) + FastMath.pow(centroid.y - point.y, 2)));
var contour = target.rawContour;
var convex = tempInt;
tempMatOfPoint.fromList(contour.toList());
Imgproc.convexHull(tempMatOfPoint, convex);
var combinedList = contour.toList();
// algorithm from team 4915
// approx poly dp time
// Contour perimeter
var peri = Imgproc.arcLength(target.rawContour, true);
// approximating a shape around the contours
// Can be tuned to allow/disallow hulls
// Approx is the number of vertices
// RamerDouglasPeucker algorithm
// we want a number between 0 and 0.16 out of a percentage from 0 to 100
// so take accuracy and divide by 600
Imgproc.approxPolyDP(target.rawContour, polyOutput, accuracyPercentage / 600.0 * peri, true);
Point[] contourArray = contour.toArray();
Point[] hullPoints = new Point[convex.rows()];
List<Integer> hullContourIdxList = convex.toList();
for (int i = 0; i < hullContourIdxList.size(); i++) {
hullPoints[i] = contourArray[hullContourIdxList.get(i)];
}
tempMat2f.fromArray(hullPoints);
var area = Imgproc.moments(polyOutput);
Imgproc.approxPolyDP(tempMat2f, polyOutput, 5, true);
// if (area.get_m00() < 200) {
// return null;
// }
var polyList = polyOutput.toList();
@@ -188,17 +206,23 @@ public class SolvePNPPipe implements Pipe<Pair<List<StandardCVPipeline.TrackedTa
try {
// top left and top right are the poly corners closest to the bouding box tl and tr
Point tl = polyList.stream().min(Comparator.comparingDouble((Point p) -> distanceBetween(p, boundingBoxCorners.get(0)))).get();
Point tr = polyList.stream().min(Comparator.comparingDouble((Point p) -> distanceBetween(p, boundingBoxCorners.get(3)))).get();
var tl = polyList.stream().min(Comparator.comparingDouble((Point p) -> distanceBetween(p, boundingBoxCorners.get(0)))).get();
var tr = polyList.stream().min(Comparator.comparingDouble((Point p) -> distanceBetween(p, boundingBoxCorners.get(3)))).get();
// var tl = polyList.stream().filter(point -> point.x < centroid.x && point.y < centroid.y).max(distanceProvider).get();
// var tr = polyList.stream().filter(point -> point.x > centroid.x && point.y < centroid.y).max(distanceProvider).get();
var bl = polyList.stream().filter(point -> point.x < centroid.x && point.y > centroid.y).max(distanceProvider).get();
var br = polyList.stream().filter(point -> point.x > centroid.x && point.y > centroid.y).max(distanceProvider).get();
// polyList = new ArrayList<>(polyList);
// polyList.removeAll(List.of(tl, tr, bl, br));
//
// var tl2 = polyList.stream().min(Comparator.comparingDouble((Point p) -> distanceBetween(p, boundingBoxCorners.get(0)))).get();
// var tr2 = polyList.stream().min(Comparator.comparingDouble((Point p) -> distanceBetween(p, boundingBoxCorners.get(3)))).get();
//
// var bl2 = polyList.stream().filter(point -> point.x < centroid.x && point.y > centroid.y).max(distanceProvider).get();
// var br2 = polyList.stream().filter(point -> point.x > centroid.x && point.y > centroid.y).max(distanceProvider).get();
target2020ResultMat.release();
target2020ResultMat.fromList(List.of(tl, bl, br, tr));
target2020ResultMat.fromList(List.of(tl, bl, br, tr));//, tr2, br2, bl2, tl2));
return target2020ResultMat;
} catch (NoSuchElementException e) {
@@ -206,8 +230,6 @@ public class SolvePNPPipe implements Pipe<Pair<List<StandardCVPipeline.TrackedTa
}
}
MatOfPoint2f polyOutput = new MatOfPoint2f();
/**
* Find the target using the outermost tape corners and a dual target.
* @param target the target.
@@ -286,118 +308,69 @@ public class SolvePNPPipe implements Pipe<Pair<List<StandardCVPipeline.TrackedTa
return boundingBoxResultMat;
}
MatOfPoint2f boundingBoxResultMat = new MatOfPoint2f();
MatOfPoint2f goodFeaturesResultMat = new MatOfPoint2f();
MatOfPoint2f goodFeatureToTrackRetval = new MatOfPoint2f();
private Mat dstNorm = new Mat();
private Mat dstNormScaled = new Mat();
List<Point> tempCornerList = new ArrayList<>();
private MatOfPoint2f refineCornersByBestTrack(MatOfPoint2f corners, Mat greyImg, StandardCVPipeline.TrackedTarget target) {
/**
* Find the corners in an image.
* @param targetImage the image to find corners in.
* @return the corners found in the image.
*/
@Deprecated
private List<Point> findCornerHarris(Mat targetImage) {
MatOfPoint approxf1 = new MatOfPoint();
var origCornerList = new ArrayList<>(corners.toList());
approxf1.fromList(origCornerList.stream()
.map(it -> new Point(it.x - target.boundingRect.x, it.y - target.boundingRect.y))
.collect(Collectors.toList())
);
var croppedImage = greyImg.submat(target.boundingRect);
// convert the image to greyscale
var gray = new Mat();
Imgproc.cvtColor(targetImage, gray, Imgproc.COLOR_BGR2GRAY);
Mat dst = Mat.zeros(targetImage.size(), CvType.CV_8U);
Imgproc.goodFeaturesToTrack(croppedImage, approxf1, 0, 0.1, 5);
// constants
final int blockSize = 2;
final int apertureSize = 3;
final double k = 0.04;
final int threshold = 200;
// at this point corners is still unmodified so let's map it
List<Point> tempList = new ArrayList<>();
/// Detecting corners
Imgproc.cornerHarris(gray, dst, blockSize, apertureSize, k);
/// Normalizing
Core.normalize(dst, dstNorm, 0, 255, Core.NORM_MINMAX);
Core.convertScaleAbs(dstNorm, dstNormScaled);
/// Drawing a circle around corners
float[] dstNormData = new float[(int) (dstNorm.total() * dstNorm.channels())];
dstNorm.get(0, 0, dstNormData);
tempCornerList.clear();
for (int i = 0; i < dstNorm.rows(); i++) {
for (int j = 0; j < dstNorm.cols(); j++) {
if ((int) dstNormData[i * dstNorm.cols() + j] > threshold) {
tempCornerList.add(new Point(j, i));
}
// shift all points back into global pose
var reshiftedList = approxf1.toList().stream().map(it -> new Point(it.x + target.boundingRect.x, it.y + target.boundingRect.y))
.collect(Collectors.toList());
for(Point p: origCornerList) {
// find the goodFeaturesToTrack corner closest to me
var closestPoint = reshiftedList.stream().min(Comparator.comparingDouble(p_ -> distanceBetween(p_, p)));
if(closestPoint.isEmpty()) {
tempList.add(p);
reshiftedList.remove(p);
} else {
tempList.add(closestPoint.get());
reshiftedList.remove(closestPoint.get());
}
}
return tempCornerList;
goodFeatureToTrackRetval.fromList(tempList);
return goodFeatureToTrackRetval;
}
@Deprecated
private MatOfPoint2f findGoodFeaturesToTrack2019(StandardCVPipeline.TrackedTarget target, Mat srcImage) {
// Set the needed parameters to find the refined corners
Size winSize = new Size(4, 4);
Size zeroZone = new Size(-1, -1); // we don't need a zero zone
TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.COUNT, 90, 0.001);
// start by looking for corners
var points__ = findBoundingBoxCorners(target).toList();
var xList = points__.stream().map(it -> it.x).sorted(Double::compare).collect(Collectors.toList());
var yList = points__.stream().map(it -> it.y).sorted(Double::compare).collect(Collectors.toList());
private boolean shouldRefineCorners = true;
var boundingTl = new Point(
xList.get(0), yList.get(0)
);
var boundingBr = new Point (
xList.get(2), yList.get(2)
);
System.out.println("tl/br:\n" + boundingTl.toString() + "\n" + boundingBr.toString());
/**
* Refine an estimated corner position using the cornerSubPixel algorithm.
*
* TODO should this be here or before the points are chosen?
*
* @param corners the corners detected -- this mat is modified!
* @param greyImg the image taken by the camera as color
* @return the updated mat, same as the corner mat passed in.
*/
private MatOfPoint2f refineCornerEstimateSubPix(MatOfPoint2f corners, Mat greyImg) {
if(!shouldRefineCorners) return corners; // just return
Imgproc.cornerSubPix(greyImg, corners, winSize, zeroZone, criteria);
var slightlyBiggerTl = new Point(
Math.max(0, boundingTl.x - 5),
Math.max(0, boundingTl.y - 5)
);
var slightlyBiggerBr = new Point(
Math.min(srcImage.rows(), boundingBr.x + 5),
Math.min(srcImage.cols(), boundingBr.y + 5)
);
var rect = new Rect(slightlyBiggerTl, slightlyBiggerBr);
var croppedImage = srcImage.submat(rect);
var corners = new MatOfPoint();
Imgproc.goodFeaturesToTrack(croppedImage, corners, 0,0.01,5);
List<Point> cornerList = new ArrayList<>(corners.toList());
// if(cornerList.size() != 8 && cornerList.size() != 4) return null;
cornerList.sort(leftRightComparator);
cornerList = cornerList.stream().map(point ->
new Point(point.x + slightlyBiggerTl.x, point.y + slightlyBiggerTl.y))
.collect(Collectors.toList());
// of these, we want the two leftmost and two rightmost points
var left1 = cornerList.get(0);
var left2 = cornerList.get(1);
var right1 = cornerList.get(0);
var right2 = cornerList.get(1);
// TODO maximize distance from the center rather than naively assume the leftmost and rightmost
// will have to do per quadrant
var leftOrder = left1.y < left2.y;
var rightOrder = right1.y < right2.y;
var tl = leftOrder ? left1 : left2;
var bl = !leftOrder ? left1 : left2;
var tr = rightOrder ? right1 : right2;
var br = !rightOrder ? right1 : right2;
goodFeaturesResultMat.release();
goodFeaturesResultMat.fromList(List.of(tl, bl, br, tr));
return goodFeaturesResultMat;
return corners;
}
private StandardCVPipeline.TrackedTarget calculatePose(MatOfPoint2f imageCornerPoints, StandardCVPipeline.TrackedTarget target) {
// NetworkTableEntry tvecE = NetworkTableInstance.getDefault().getTable("SmartDashboard").getEntry("tvec");
// NetworkTableEntry rvecE = NetworkTableInstance.getDefault().getTable("SmartDashboard").getEntry("rvec");
public StandardCVPipeline.TrackedTarget calculatePose(MatOfPoint2f imageCornerPoints, StandardCVPipeline.TrackedTarget target) {
if(objPointsMat.rows() != imageCornerPoints.rows() || cameraMatrix.rows() < 2 || distortionCoefficients.cols() < 4) {
System.err.println("can't do solvePNP with invalid params!");
return null;
@@ -412,35 +385,43 @@ public class SolvePNPPipe implements Pipe<Pair<List<StandardCVPipeline.TrackedTa
return null;
}
// tvecE.setString(tVec.dump());
// rvecE.setString(rVec.dump());
// Algorithm from team 5190 Green Hope Falcons
// var tilt_angle = 0.0; // TODO add to settings
// the left/right distance to the target, unchanged by tilt
var x = tVec.get(0, 0)[0];
var z = FastMath.sin(tilt_angle) * tVec.get(1, 0)[0] + tVec.get(2, 0)[0] * FastMath.cos(tilt_angle);
// distance in the horizontal plane between camera and target
var distance = FastMath.sqrt(x * x + z * z);
// Z distance in the flat plane is given by
// Z_field = z cos theta + y sin theta
var z = tVec.get(2, 0)[0] * FastMath.cos(tilt_angle) + tVec.get(1, 0)[0] * FastMath.sin(tilt_angle);
// horizontal angle between center camera and target
@SuppressWarnings("SuspiciousNameCombination")
var angle1 = FastMath.atan2(x, z);
// find skew of the target relative to the camera
// from ligerbots:
// rot, _ = cv2.Rodrigues(rvec)
// rot_inv = rot.transpose()
// pzero_world = numpy.matmul(rot_inv, -tvec)
// angle2 = math.atan2(pzero_world[0][0], pzero_world[2][0]
Calib3d.Rodrigues(rVec, rodriguez);
Core.transpose(rodriguez, rot_inv);
Core.transpose(rodriguez, rot_inv); // rodrigurz.t()
// This should be pzero_world = numpy.matmul(rot_inv, -tvec)
// pzero_world = rot_inv.mul(matScale(tVec, -1));
scaledTvec = matScale(tVec, -1);
Core.gemm(rot_inv, scaledTvec, 1, kMat, 0, pzero_world);
var angle2 = FastMath.atan2(pzero_world.get(0, 0)[0], pzero_world.get(2, 0)[0]);
var targetAngle = -angle1; // radians
var targetRotation = -angle2; // radians
var targetDistance = distance * 25.4 / 1000d / distanceDivisor; // This should be meters
var targetLocation = new Translation2d(targetDistance * FastMath.cos(targetAngle), targetDistance * FastMath.sin(targetAngle));
// We want a vector that is X forward and Y left.
// We have a Z_field (out of the camera projected onto the field), and an X left/right.
// so Z_field becomes X, and X becomes Y
//noinspection SuspiciousNameCombination
var targetLocation = new Translation2d(z, -x).times(25.4 / 1000d / distanceDivisor);
target.cameraRelativePose = new Pose2d(targetLocation, new Rotation2d(targetRotation));
target.rVector = rVec;
target.tVector = tVec;

View File

@@ -4,6 +4,7 @@ import com.chameleonvision.Exceptions.DuplicatedKeyException;
import com.chameleonvision.Main;
import com.chameleonvision.config.ConfigManager;
import com.chameleonvision.network.NetworkIPMode;
import com.chameleonvision.network.NetworkManager;
import com.chameleonvision.networktables.NetworkTablesManager;
import com.chameleonvision.util.Helpers;
import com.chameleonvision.util.Platform;
@@ -53,8 +54,17 @@ public class RequestHandler {
ConfigManager.settings.gateway = (String) map.get("gateway");
ConfigManager.settings.hostname = (String) map.get("hostname");
ConfigManager.saveGeneralSettings();
// setting up network config after saving
boolean isStatic = ConfigManager.settings.connectionType.equals(NetworkIPMode.STATIC);
if (NetworkManager.setHostname(ConfigManager.settings.hostname) &&
NetworkManager.setNetwork(isStatic, ConfigManager.settings.ip, ConfigManager.settings.netmask, ConfigManager.settings.gateway)) {
ctx.status(200);
} else {
ctx.result("Something went wrong while setting network configuration");
ctx.status(501);
}
SocketHandler.sendFullSettings();
ctx.status(200);
} catch (JsonProcessingException e) {
ctx.status(500);
}

View File

@@ -52,7 +52,8 @@ public class SocketHandler {
@SuppressWarnings("unchecked")
void onBinaryMessage(WsBinaryMessageContext context) throws Exception {
Map<String, Object> deserialized = objectMapper.readValue((byte[]) ArrayUtils.toPrimitive(context.data()),
new TypeReference<>(){});
new TypeReference<>() {
});
for (Map.Entry<String, Object> entry : deserialized.entrySet()) {
try {
VisionProcess currentProcess = VisionManager.getCurrentUIVisionProcess();
@@ -168,6 +169,10 @@ public class SocketHandler {
currentCamera.setBrightness((Integer) entry.getValue());
break;
}
case "gain": {
currentCamera.setGain((Integer) entry.getValue());
break;
}
case "videoModeIndex": {
if (currentPipeline instanceof StandardCVPipeline)
((StandardCVPipeline) currentPipeline).settings.point = new ArrayList<>();//This will reset the calibration

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.v-chip:not(.v-chip--outlined).accent,.v-chip:not(.v-chip--outlined).error,.v-chip:not(.v-chip--outlined).info,.v-chip:not(.v-chip--outlined).primary,.v-chip:not(.v-chip--outlined).secondary,.v-chip:not(.v-chip--outlined).success,.v-chip:not(.v-chip--outlined).warning{color:#fff}.theme--light.v-chip{border-color:rgba(0,0,0,.12);color:rgba(0,0,0,.87)}.theme--light.v-chip:not(.v-chip--active){background:#e0e0e0}.theme--light.v-chip:hover:before{opacity:.04}.theme--light.v-chip--active:before,.theme--light.v-chip--active:hover:before,.theme--light.v-chip:focus:before{opacity:.12}.theme--light.v-chip--active:focus:before{opacity:.16}.theme--dark.v-chip{border-color:hsla(0,0%,100%,.12);color:#fff}.theme--dark.v-chip:not(.v-chip--active){background:#555}.theme--dark.v-chip:hover:before{opacity:.08}.theme--dark.v-chip--active:before,.theme--dark.v-chip--active:hover:before,.theme--dark.v-chip:focus:before{opacity:.24}.theme--dark.v-chip--active:focus:before{opacity:.32}.v-chip{-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:default;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;line-height:20px;max-width:100%;outline:none;overflow:hidden;padding:0 12px;position:relative;text-decoration:none;-webkit-transition-duration:.28s;transition-duration:.28s;-webkit-transition-property:opacity,-webkit-box-shadow;transition-property:opacity,-webkit-box-shadow;transition-property:box-shadow,opacity;transition-property:box-shadow,opacity,-webkit-box-shadow;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);vertical-align:middle;white-space:nowrap}.v-chip:before{background-color:currentColor;bottom:0;border-radius:inherit;content:"";left:0;opacity:0;position:absolute;pointer-events:none;right:0;top:0}.v-chip .v-avatar{height:24px!important;min-width:24px!important;width:24px!important}.v-chip .v-icon{font-size:24px}.v-application--is-ltr .v-chip .v-avatar--left,.v-application--is-ltr .v-chip .v-icon--left{margin-left:-6px;margin-right:8px}.v-application--is-ltr .v-chip .v-avatar--right,.v-application--is-ltr .v-chip .v-icon--right,.v-application--is-rtl .v-chip .v-avatar--left,.v-application--is-rtl .v-chip .v-icon--left{margin-left:8px;margin-right:-6px}.v-application--is-rtl .v-chip .v-avatar--right,.v-application--is-rtl .v-chip .v-icon--right{margin-left:-6px;margin-right:8px}.v-chip:not(.v-chip--no-color) .v-icon{color:inherit}.v-chip__close.v-icon{font-size:18px;max-height:18px;max-width:18px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.v-application--is-ltr .v-chip__close.v-icon.v-icon--right{margin-right:-4px}.v-application--is-rtl .v-chip__close.v-icon.v-icon--right{margin-left:-4px}.v-chip__close.v-icon:active,.v-chip__close.v-icon:focus,.v-chip__close.v-icon:hover{opacity:.72}.v-chip__content{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;height:100%;max-width:100%}.v-chip--active .v-icon{color:inherit}.v-chip--link:before{-webkit-transition:opacity .3s cubic-bezier(.25,.8,.5,1);transition:opacity .3s cubic-bezier(.25,.8,.5,1)}.v-chip--link:focus:before{opacity:.32}.v-chip--clickable{cursor:pointer}.v-chip--clickable:active{-webkit-box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12);box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12)}.v-chip--disabled{opacity:.4;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.v-chip__filter{max-width:24px}.v-chip__filter.v-icon{color:inherit}.v-chip__filter.expand-x-transition-enter,.v-chip__filter.expand-x-transition-leave-active{margin:0}.v-chip--pill .v-chip__filter{margin-right:0 16px 0 0}.v-chip--pill .v-avatar{height:32px!important;width:32px!important}.v-application--is-ltr .v-chip--pill .v-avatar--left{margin-left:-12px}.v-application--is-ltr .v-chip--pill .v-avatar--right,.v-application--is-rtl .v-chip--pill .v-avatar--left{margin-right:-12px}.v-application--is-rtl .v-chip--pill .v-avatar--right{margin-left:-12px}.v-chip--label{border-radius:4px!important}.v-chip.v-chip--outlined{border-width:thin;border-style:solid}.v-chip.v-chip--outlined:not(.v-chip--active):before{opacity:0}.v-chip.v-chip--outlined.v-chip--active:before{opacity:.08}.v-chip.v-chip--outlined .v-icon{color:inherit}.v-chip.v-chip--outlined.v-chip.v-chip{background-color:transparent!important}.v-chip.v-chip--selected{background:transparent}.v-chip.v-chip--selected:after{opacity:.28}.v-chip.v-size--x-small{border-radius:8px;font-size:10px;height:16px}.v-chip.v-size--small{border-radius:12px;font-size:12px;height:24px}.v-chip.v-size--default{border-radius:16px;font-size:14px;height:32px}.v-chip.v-size--large{border-radius:27px;font-size:16px;height:54px}.v-chip.v-size--x-large{border-radius:33px;font-size:18px;height:66px}

View File

@@ -1 +0,0 @@
.hover[data-v-912b6e62]:hover{color:#fff!important}.v-tooltip{display:inline}.v-tooltip__content{background:rgba(97,97,97,.9);color:#fff;border-radius:4px;font-size:14px;line-height:22px;display:inline-block;padding:5px 16px;position:absolute;text-transform:none;width:auto;opacity:1;pointer-events:none}.v-tooltip__content--fixed{position:fixed}.v-tooltip__content[class*=-active]{-webkit-transition-timing-function:cubic-bezier(0,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1)}.v-tooltip__content[class*=enter-active]{-webkit-transition-duration:.15s;transition-duration:.15s}.v-tooltip__content[class*=leave-active]{-webkit-transition-duration:75ms;transition-duration:75ms}.colsClass[data-v-3b74cf0c]{padding:0!important}.videoClass[data-v-3b74cf0c]{text-align:center}.tableClass[data-v-3b74cf0c]{padding-top:5px;width:70%;text-align:center}th[data-v-3b74cf0c]{width:80px;text-align:center}.v-input--checkbox.v-input--indeterminate.v-input--is-disabled{opacity:.6}.v-dialog{border-radius:4px;margin:24px;overflow-y:auto;pointer-events:auto;-webkit-transition:.3s cubic-bezier(.25,.8,.25,1);transition:.3s cubic-bezier(.25,.8,.25,1);width:100%;z-index:inherit;-webkit-box-shadow:0 11px 15px -7px rgba(0,0,0,.2),0 24px 38px 3px rgba(0,0,0,.14),0 9px 46px 8px rgba(0,0,0,.12);box-shadow:0 11px 15px -7px rgba(0,0,0,.2),0 24px 38px 3px rgba(0,0,0,.14),0 9px 46px 8px rgba(0,0,0,.12)}.v-dialog:not(.v-dialog--fullscreen){max-height:90%}.v-dialog>*{width:100%}.v-dialog>.v-card>.v-card__title{font-size:1.25rem;font-weight:500;letter-spacing:.0125em;padding:16px 24px 10px}.v-dialog>.v-card>.v-card__text{padding:0 24px 20px}.v-dialog__content{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:100%;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;left:0;pointer-events:none;position:fixed;top:0;-webkit-transition:.2s cubic-bezier(.25,.8,.25,1),z-index 1ms;transition:.2s cubic-bezier(.25,.8,.25,1),z-index 1ms;width:100%;z-index:6;outline:none}.v-dialog__activator,.v-dialog__activator *{cursor:pointer}.v-dialog__container{display:inline}.v-dialog--animated{-webkit-animation-duration:.15s;animation-duration:.15s;-webkit-animation-name:animate-dialog;animation-name:animate-dialog;-webkit-animation-timing-function:cubic-bezier(.25,.8,.25,1);animation-timing-function:cubic-bezier(.25,.8,.25,1)}.v-dialog--fullscreen{border-radius:0;margin:0;height:100%;position:fixed;overflow-y:auto;top:0;left:0}.v-dialog--fullscreen>.v-card{min-height:100%;min-width:100%;margin:0!important;padding:0!important}.v-dialog--scrollable,.v-dialog--scrollable>form{display:-webkit-box;display:-ms-flexbox;display:flex}.v-dialog--scrollable>.v-card,.v-dialog--scrollable>form>.v-card{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1 1 100%;flex:1 1 100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:100%;max-width:100%}.v-dialog--scrollable>.v-card>.v-card__actions,.v-dialog--scrollable>.v-card>.v-card__title,.v-dialog--scrollable>form>.v-card>.v-card__actions,.v-dialog--scrollable>form>.v-card>.v-card__title{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}.v-dialog--scrollable>.v-card>.v-card__text,.v-dialog--scrollable>form>.v-card>.v-card__text{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;overflow-y:auto}@-webkit-keyframes animate-dialog{0%{-webkit-transform:scale(1);transform:scale(1)}50%{-webkit-transform:scale(1.03);transform:scale(1.03)}to{-webkit-transform:scale(1);transform:scale(1)}}@keyframes animate-dialog{0%{-webkit-transform:scale(1);transform:scale(1)}50%{-webkit-transform:scale(1.03);transform:scale(1.03)}to{-webkit-transform:scale(1);transform:scale(1)}}.theme--light.v-overlay{color:rgba(0,0,0,.87)}.theme--dark.v-overlay{color:#fff}.v-overlay{-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-radius:inherit;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:fixed;top:0;left:0;right:0;bottom:0;pointer-events:none;-webkit-transition:.3s cubic-bezier(.25,.8,.5,1),z-index 1ms;transition:.3s cubic-bezier(.25,.8,.5,1),z-index 1ms}.v-overlay__content{position:relative}.v-overlay__scrim{border-radius:inherit;bottom:0;height:100%;left:0;position:absolute;right:0;top:0;-webkit-transition:inherit;transition:inherit;width:100%;will-change:opacity}.v-overlay--absolute{position:absolute}.v-overlay--active{pointer-events:auto;-ms-touch-action:none;touch-action:none}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.v-input--checkbox.v-input--indeterminate.v-input--is-disabled{opacity:.6}.videoClass[data-v-7880bdc2]{text-align:center}.videoClass img[data-v-7880bdc2]{padding-top:10px;height:auto!important;width:75%;vertical-align:middle}.colsClass[data-v-7880bdc2]{padding:0!important}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.theme--light.v-input--range-slider.v-input--slider.v-input--is-disabled .v-slider.v-slider .v-slider__thumb{background:#fafafa}.theme--dark.v-input--range-slider.v-input--slider.v-input--is-disabled .v-slider.v-slider .v-slider__thumb{background:#424242}.v-input--range-slider.v-input--is-disabled .v-slider__track-fill{display:none}.v-input--range-slider.v-input--is-disabled.v-input--slider .v-slider.v-slider .v-slider__thumb{border-color:transparent}

View File

@@ -1 +0,0 @@
.theme--light.v-radio--is-disabled label{color:rgba(0,0,0,.38)}.theme--light.v-radio--is-disabled .v-icon{color:rgba(0,0,0,.26)!important}.theme--dark.v-radio--is-disabled label{color:hsla(0,0%,100%,.5)}.theme--dark.v-radio--is-disabled .v-icon{color:hsla(0,0%,100%,.3)!important}.v-radio{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:auto;margin-right:16px;outline:none}.v-radio--is-disabled{pointer-events:none}.theme--light.v-input--selection-controls.v-input--is-disabled:not(.v-input--indeterminate) .v-icon{color:rgba(0,0,0,.26)!important}.theme--dark.v-input--selection-controls.v-input--is-disabled:not(.v-input--indeterminate) .v-icon{color:hsla(0,0%,100%,.3)!important}.v-input--selection-controls{margin-top:16px;padding-top:4px}.v-input--selection-controls .v-input__append-outer,.v-input--selection-controls .v-input__prepend-outer{margin-top:0;margin-bottom:0}.v-input--selection-controls .v-input__control{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;width:auto}.v-input--selection-controls:not(.v-input--hide-details) .v-input__slot{margin-bottom:12px}.v-input--selection-controls__input{color:inherit;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;height:24px;position:relative;margin-right:8px;-webkit-transition:.3s cubic-bezier(.25,.8,.25,1);transition:.3s cubic-bezier(.25,.8,.25,1);-webkit-transition-property:color,-webkit-transform;transition-property:color,-webkit-transform;transition-property:color,transform;transition-property:color,transform,-webkit-transform;width:24px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.v-application--is-rtl .v-input--selection-controls__input{margin-right:0;margin-left:8px}.v-input--selection-controls__input input[role=checkbox],.v-input--selection-controls__input input[role=radio],.v-input--selection-controls__input input[role=switch]{position:absolute;opacity:0;width:100%;height:100%;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.v-input--selection-controls__input+.v-label{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.v-input--selection-controls__ripple{border-radius:50%;cursor:pointer;height:34px;position:absolute;-webkit-transition:inherit;transition:inherit;width:34px;left:-12px;top:calc(50% - 24px);margin:7px}.v-input--selection-controls__ripple:before{border-radius:inherit;bottom:0;content:"";position:absolute;opacity:.2;left:0;right:0;top:0;-webkit-transform-origin:center center;transform-origin:center center;-webkit-transform:scale(.2);transform:scale(.2);-webkit-transition:inherit;transition:inherit}.v-input--selection-controls__ripple .v-ripple__container{-webkit-transform:scale(1.2);transform:scale(1.2)}.v-input--selection-controls.v-input{-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.v-input--selection-controls.v-input .v-label{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;top:0;height:auto}.v-input--selection-controls.v-input--is-focused .v-input--selection-controls__ripple:before,.v-input--selection-controls .v-radio--is-focused .v-input--selection-controls__ripple:before{background:currentColor;opacity:.4;-webkit-transform:scale(1.2);transform:scale(1.2)}.v-input--selection-controls .v-input--selection-controls__input:hover .v-input--selection-controls__ripple:before{background:currentColor;-webkit-transform:scale(1.2);transform:scale(1.2);-webkit-transition:none;transition:none}.v-input--radio-group__input{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.v-input--radio-group--column .v-input--radio-group__input>.v-label{padding-bottom:8px}.v-input--radio-group--row .v-input--radio-group__input>.v-label{padding-right:8px}.v-input--radio-group--row .v-input--radio-group__input{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:wrap;flex-wrap:wrap}.v-input--radio-group--column .v-radio:not(:last-child):not(:only-child){margin-bottom:8px}.v-input--radio-group--column .v-input--radio-group__input{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.videoClass[data-v-057e00f3]{text-align:center}.videoClass img[data-v-057e00f3]{padding-top:10px;height:auto!important;width:75%;vertical-align:middle}.colsClass[data-v-057e00f3]{padding:0!important}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.v-input--checkbox.v-input--indeterminate.v-input--is-disabled{opacity:.6}.theme--light.v-input--selection-controls.v-input--is-disabled:not(.v-input--indeterminate) .v-icon{color:rgba(0,0,0,.26)!important}.theme--dark.v-input--selection-controls.v-input--is-disabled:not(.v-input--indeterminate) .v-icon{color:hsla(0,0%,100%,.3)!important}.v-input--selection-controls{margin-top:16px;padding-top:4px}.v-input--selection-controls .v-input__append-outer,.v-input--selection-controls .v-input__prepend-outer{margin-top:0;margin-bottom:0}.v-input--selection-controls:not(.v-input--hide-details) .v-input__slot{margin-bottom:12px}.v-input--selection-controls__input{color:inherit;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;height:24px;position:relative;-webkit-transition:.3s cubic-bezier(.25,.8,.25,1);transition:.3s cubic-bezier(.25,.8,.25,1);-webkit-transition-property:color,-webkit-transform;transition-property:color,-webkit-transform;transition-property:color,transform;transition-property:color,transform,-webkit-transform;width:24px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.v-application--is-ltr .v-input--selection-controls__input{margin-right:8px}.v-application--is-rtl .v-input--selection-controls__input{margin-left:8px}.v-input--selection-controls__input input[role=checkbox],.v-input--selection-controls__input input[role=radio],.v-input--selection-controls__input input[role=switch]{position:absolute;opacity:0;width:100%;height:100%;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.v-input--selection-controls__input+.v-label{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.v-input--selection-controls__ripple{border-radius:50%;cursor:pointer;height:34px;position:absolute;-webkit-transition:inherit;transition:inherit;width:34px;left:-12px;top:calc(50% - 24px);margin:7px}.v-input--selection-controls__ripple:before{border-radius:inherit;bottom:0;content:"";position:absolute;opacity:.2;left:0;right:0;top:0;-webkit-transform-origin:center center;transform-origin:center center;-webkit-transform:scale(.2);transform:scale(.2);-webkit-transition:inherit;transition:inherit}.v-input--selection-controls__ripple .v-ripple__container{-webkit-transform:scale(1.2);transform:scale(1.2)}.v-input--selection-controls.v-input--dense .v-input--selection-controls__ripple{width:28px;height:28px;left:-11px}.v-input--selection-controls.v-input--dense:not(.v-input--switch) .v-input--selection-controls__ripple{top:calc(50% - 21px)}.v-input--selection-controls.v-input{-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.v-input--selection-controls.v-input .v-label{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;top:0;height:auto}.v-input--selection-controls.v-input--is-focused .v-input--selection-controls__ripple:before,.v-input--selection-controls .v-radio--is-focused .v-input--selection-controls__ripple:before{background:currentColor;opacity:.4;-webkit-transform:scale(1.2);transform:scale(1.2)}.v-input--selection-controls .v-input--selection-controls__input:hover .v-input--selection-controls__ripple:before{background:currentColor;-webkit-transform:scale(1.2);transform:scale(1.2);-webkit-transition:none;transition:none}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.png><title>Chameleon Vision</title><link rel=stylesheet href=/Roboto.css><link href=/css/chunk-218b16fc.84e78a37.css rel=prefetch><link href=/css/chunk-234aed0c.5856ebfe.css rel=prefetch><link href=/css/chunk-30cf0ee8.437bbfd3.css rel=prefetch><link href=/css/chunk-33f18466.5da4dc56.css rel=prefetch><link href=/css/chunk-402ab08c.d47fe89d.css rel=prefetch><link href=/css/chunk-74cde756.7753bf1c.css rel=prefetch><link href=/css/chunk-79a507e8.4c388212.css rel=prefetch><link href=/css/chunk-7a810817.e757f52a.css rel=prefetch><link href=/css/chunk-7cf477eb.2ea217a5.css rel=prefetch><link href=/css/chunk-8bc075b4.52ef46aa.css rel=prefetch><link href=/js/chunk-1c4e016e.3c63bd07.js rel=prefetch><link href=/js/chunk-218b16fc.85ae3dfa.js rel=prefetch><link href=/js/chunk-234aed0c.5ce036d9.js rel=prefetch><link href=/js/chunk-30cf0ee8.a08facb0.js rel=prefetch><link href=/js/chunk-33f18466.b80a16b3.js rel=prefetch><link href=/js/chunk-3ae1c3ad.5aface64.js rel=prefetch><link href=/js/chunk-402ab08c.6a0cfa00.js rel=prefetch><link href=/js/chunk-74cde756.538b7b46.js rel=prefetch><link href=/js/chunk-79a507e8.a8f72f00.js rel=prefetch><link href=/js/chunk-7a810817.6fa5d1de.js rel=prefetch><link href=/js/chunk-7cf477eb.ccf582bf.js rel=prefetch><link href=/js/chunk-8bc075b4.c1dd0af7.js rel=prefetch><link href=/css/app.9a11344b.css rel=preload as=style><link href=/css/chunk-vendors.cc4c495b.css rel=preload as=style><link href=/js/app.b9fa435a.js rel=preload as=script><link href=/js/chunk-vendors.90d5c4b3.js rel=preload as=script><link href=/css/chunk-vendors.cc4c495b.css rel=stylesheet><link href=/css/app.9a11344b.css rel=stylesheet></head><body><noscript><strong>We're sorry but Chameleon Vision doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.90d5c4b3.js></script><script src=/js/app.b9fa435a.js></script></body></html>
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.png><title>Chameleon Vision</title><link rel=stylesheet href=/Roboto.css><link href=/css/chunk-01759076.2eb9f3d3.css rel=prefetch><link href=/css/chunk-20681be8.5ac7b59c.css rel=prefetch><link href=/css/chunk-369f5d2c.eaa0163e.css rel=prefetch><link href=/css/chunk-423191c4.0a21637d.css rel=prefetch><link href=/css/chunk-586d85e4.873c9690.css rel=prefetch><link href=/css/chunk-5af10b37.5b8e5b27.css rel=prefetch><link href=/css/chunk-6516d830.e951ae66.css rel=prefetch><link href=/css/chunk-65ac8106.108b4a7c.css rel=prefetch><link href=/css/chunk-6911ca5e.61379667.css rel=prefetch><link href=/css/chunk-6e69a154.38f70fef.css rel=prefetch><link href=/css/chunk-6f8eef3f.09316a61.css rel=prefetch><link href=/css/chunk-7d8e2978.c741c172.css rel=prefetch><link href=/js/chunk-01759076.5c267949.js rel=prefetch><link href=/js/chunk-20681be8.c913200b.js rel=prefetch><link href=/js/chunk-2d0c7972.adbbf5d7.js rel=prefetch><link href=/js/chunk-369f5d2c.8e3b6396.js rel=prefetch><link href=/js/chunk-423191c4.430d7b21.js rel=prefetch><link href=/js/chunk-586d85e4.7c1f7039.js rel=prefetch><link href=/js/chunk-5af10b37.cf8850a1.js rel=prefetch><link href=/js/chunk-6516d830.270065e7.js rel=prefetch><link href=/js/chunk-65ac8106.19dca69f.js rel=prefetch><link href=/js/chunk-6911ca5e.6a2b6398.js rel=prefetch><link href=/js/chunk-6e69a154.4738d1b9.js rel=prefetch><link href=/js/chunk-6f8eef3f.5538449a.js rel=prefetch><link href=/js/chunk-7d8e2978.07319db3.js rel=prefetch><link href=/css/app.9a11344b.css rel=preload as=style><link href=/css/chunk-vendors.ae417f2a.css rel=preload as=style><link href=/js/app.cca5a176.js rel=preload as=script><link href=/js/chunk-vendors.36448f71.js rel=preload as=script><link href=/css/chunk-vendors.ae417f2a.css rel=stylesheet><link href=/css/app.9a11344b.css rel=stylesheet></head><body><noscript><strong>We're sorry but Chameleon Vision doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.36448f71.js></script><script src=/js/app.cca5a176.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-20681be8"],{"8adc":function(t,e,i){},cc20:function(t,e,i){"use strict";i("8adc");var s=i("58df"),a=i("0789"),l=i("9d26"),o=i("a9ad"),c=i("4e82"),n=i("7560"),h=i("f2e7"),r=i("1c87"),p=i("af2b"),d=i("d9bd");e["a"]=Object(s["a"])(o["a"],p["a"],r["a"],n["a"],Object(c["a"])("chipGroup"),Object(h["b"])("inputValue")).extend({name:"v-chip",props:{active:{type:Boolean,default:!0},activeClass:{type:String,default(){return this.chipGroup?this.chipGroup.activeClass:""}},close:Boolean,closeIcon:{type:String,default:"$delete"},disabled:Boolean,draggable:Boolean,filter:Boolean,filterIcon:{type:String,default:"$complete"},label:Boolean,link:Boolean,outlined:Boolean,pill:Boolean,tag:{type:String,default:"span"},textColor:String,value:null},data:()=>({proxyClass:"v-chip--active"}),computed:{classes(){return{"v-chip":!0,...r["a"].options.computed.classes.call(this),"v-chip--clickable":this.isClickable,"v-chip--disabled":this.disabled,"v-chip--draggable":this.draggable,"v-chip--label":this.label,"v-chip--link":this.isLink,"v-chip--no-color":!this.color,"v-chip--outlined":this.outlined,"v-chip--pill":this.pill,"v-chip--removable":this.hasClose,...this.themeClasses,...this.sizeableClasses,...this.groupClasses}},hasClose(){return Boolean(this.close)},isClickable(){return Boolean(r["a"].options.computed.isClickable.call(this)||this.chipGroup)}},created(){const t=[["outline","outlined"],["selected","input-value"],["value","active"],["@input","@active.sync"]];t.forEach(([t,e])=>{this.$attrs.hasOwnProperty(t)&&Object(d["a"])(t,e,this)})},methods:{click(t){this.$emit("click",t),this.chipGroup&&this.toggle()},genFilter(){const t=[];return this.isActive&&t.push(this.$createElement(l["a"],{staticClass:"v-chip__filter",props:{left:!0}},this.filterIcon)),this.$createElement(a["b"],t)},genClose(){return this.$createElement(l["a"],{staticClass:"v-chip__close",props:{right:!0},on:{click:t=>{t.stopPropagation(),this.$emit("click:close"),this.$emit("update:active",!1)}}},this.closeIcon)},genContent(){return this.$createElement("span",{staticClass:"v-chip__content"},[this.filter&&this.genFilter(),this.$slots.default,this.hasClose&&this.genClose()])}},render(t){const e=[this.genContent()];let{tag:i,data:s}=this.generateRouteLink();s.attrs={...s.attrs,draggable:this.draggable?"true":void 0,tabindex:this.chipGroup&&!this.disabled?0:s.attrs.tabindex},s.directives.push({name:"show",value:this.active}),s=this.setBackgroundColor(this.color,s);const a=this.textColor||this.outlined&&this.color;return t(i,this.setTextColor(a,s),e)}})}}]);
//# sourceMappingURL=chunk-20681be8.c913200b.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0c7972"],{"50ef":function(e,t,a){"use strict";a.r(t);var n=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",[a("CVslider",{attrs:{name:"Exposure",min:0,max:100},on:{input:function(t){return e.handleData("exposure")}},model:{value:e.value.exposure,callback:function(t){e.$set(e.value,"exposure",t)},expression:"value.exposure"}}),a("CVslider",{attrs:{name:"Brightness",min:0,max:100},on:{input:function(t){return e.handleData("brightness")}},model:{value:e.value.brightness,callback:function(t){e.$set(e.value,"brightness",t)},expression:"value.brightness"}}),-1!==e.value.gain?a("CVslider",{attrs:{name:"Gain",min:0,max:100},on:{input:function(t){return e.handleData("gain")}},model:{value:e.value.gain,callback:function(t){e.$set(e.value,"gain",t)},expression:"value.gain"}}):e._e(),a("CVselect",{attrs:{name:"Orientation",list:["Normal","90° CW","180°","90° CCW"]},on:{input:function(t){return e.handleData("rotationMode")}},model:{value:e.value.rotationMode,callback:function(t){e.$set(e.value,"rotationMode",t)},expression:"value.rotationMode"}}),a("CVselect",{attrs:{name:"Resolution",list:e.resolutionList},on:{input:function(t){return e.handleData("videoModeIndex")}},model:{value:e.value.videoModeIndex,callback:function(t){e.$set(e.value,"videoModeIndex",t)},expression:"value.videoModeIndex"}}),a("CVselect",{attrs:{name:"Stream Resolution",list:e.streamResolutionList},on:{input:function(t){return e.handleData("streamDivisor")}},model:{value:e.value.streamDivisor,callback:function(t){e.$set(e.value,"streamDivisor",t)},expression:"value.streamDivisor"}})],1)},o=[],i=a("1447"),s=a("8384"),l={name:"Input",props:["value"],components:{CVslider:i["a"],CVselect:s["a"]},methods:{handleData(e){this.handleInput(e,this.value[e]),this.$emit("update")}},data(){return{t:0,a:1}},computed:{resolutionList:{get(){let e=[];for(let t of this.$store.state.resolutionList)e.push(`${t["width"]} X ${t["height"]} at ${t["fps"]} FPS, ${t["pixelFormat"]}`);return e}},streamResolutionList:{get(){let e=this.$store.state.resolutionList[this.value.videoModeIndex],t=[];t.push(`${Math.floor(e["width"])} X ${Math.floor(e["height"])}`);for(let a=2;a<=6;a+=2)t.push(`${Math.floor(e["width"]/a)} X ${Math.floor(e["height"]/a)}`);return t}}}},u=l,r=a("2877"),d=Object(r["a"])(u,n,o,!1,null,"cb80c2b0",null);t["default"]=d.exports}}]);
//# sourceMappingURL=chunk-2d0c7972.adbbf5d7.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-3ae1c3ad"],{1447:function(e,t,a){"use strict";var n=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",[a("v-row",{attrs:{dense:"",align:"center"}},[a("v-col",{attrs:{cols:2}},[a("span",[e._v(e._s(e.name))])]),a("v-col",{attrs:{cols:10}},[a("v-slider",{staticClass:"align-center",attrs:{value:e.localValue,dark:"",max:e.max,min:e.min,"hide-details":"",color:"#4baf62",step:e.step},on:{start:function(t){e.isClicked=!0},end:function(t){e.isClicked=!1},change:e.handleclick,input:e.handleInput},scopedSlots:e._u([{key:"append",fn:function(){return[a("v-text-field",{staticClass:"mt-0 pt-0",staticStyle:{width:"50px"},attrs:{dark:"",max:e.max,min:e.min,value:e.localValue,"hide-details":"","single-line":"",type:"number",step:e.step},on:{input:e.handleChange,focus:function(t){e.isFocused=!0},blur:function(t){e.isFocused=!1}}})]},proxy:!0}])})],1)],1)],1)},l=[],i={name:"Slider",props:["min","max","name","value","step"],data(){return{isFocused:!1,isClicked:!1}},methods:{handleChange(e){this.isFocused&&(this.localValue=parseFloat(e))},handleInput(e){!this.isFocused&&this.isClicked&&(this.localValue=e)},handleclick(e){this.isFocused||(this.localValue=e)}},computed:{localValue:{get(){return this.value},set(e){this.$emit("input",e)}}}},s=i,u=a("2877"),r=a("6544"),o=a.n(r),c=a("62ad"),d=a("0fd9"),p=a("ba0d"),m=a("8654"),v=Object(u["a"])(s,n,l,!1,null,"027e70b6",null);t["a"]=v.exports;o()(v,{VCol:c["a"],VRow:d["a"],VSlider:p["a"],VTextField:m["a"]})},"5c73":function(e,t,a){"use strict";a.r(t);var n=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",[a("CVrangeSlider",{attrs:{name:"Area",min:0,max:100,step:.1},on:{input:function(t){return e.handleData("area")}},model:{value:e.value.area,callback:function(t){e.$set(e.value,"area",t)},expression:"value.area"}}),a("CVrangeSlider",{attrs:{name:"Ratio (W/H)",min:0,max:100,step:.1},on:{input:function(t){return e.handleData("ratio")}},model:{value:e.value.ratio,callback:function(t){e.$set(e.value,"ratio",t)},expression:"value.ratio"}}),a("CVrangeSlider",{attrs:{name:"Extent",min:0,max:100},on:{input:function(t){return e.handleData("extent")}},model:{value:e.value.extent,callback:function(t){e.$set(e.value,"extent",t)},expression:"value.extent"}}),a("CVslider",{attrs:{name:"Speckle Rejection",min:0,max:100},on:{input:function(t){return e.handleData("speckle")}},model:{value:e.value.speckle,callback:function(t){e.$set(e.value,"speckle",t)},expression:"value.speckle"}}),a("CVselect",{attrs:{name:"Target Group",list:["Single","Dual"]},on:{input:function(t){return e.handleData("targetGroup")}},model:{value:e.value.targetGroup,callback:function(t){e.$set(e.value,"targetGroup",t)},expression:"value.targetGroup"}}),a("CVselect",{attrs:{name:"Target Intersection",list:["None","Up","Down","Left","Right"],disabled:e.isDisabled},on:{input:function(t){return e.handleData("targetIntersection")}},model:{value:e.value.targetIntersection,callback:function(t){e.$set(e.value,"targetIntersection",t)},expression:"value.targetIntersection"}})],1)},l=[],i=a("1029"),s=a("8384"),u=a("1447"),r={name:"Contours",props:["value"],components:{CVrangeSlider:i["a"],CVselect:s["a"],CVslider:u["a"]},methods:{handleData(e){this.handleInput(e,this.value[e]),this.$emit("update")}},data(){return{}},computed:{isDisabled(){return 0===this.value.targetGroup}}},o=r,c=a("2877"),d=Object(c["a"])(o,n,l,!1,null,"003f692e",null);t["default"]=d.exports}}]);
//# sourceMappingURL=chunk-3ae1c3ad.5aface64.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More