Added Arduino and Compression
This commit is contained in:
parent
838e6e9d89
commit
b023b561d8
46
Arduino/CompressionTest1/CompressionTest1.ino
Normal file
46
Arduino/CompressionTest1/CompressionTest1.ino
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include <bcconfig.h>
|
||||||
|
#include <BigNumber.h>
|
||||||
|
#include <number.h>
|
||||||
|
|
||||||
|
#define numberOfSensors 50
|
||||||
|
int flexSensorPins[] = {A0, A1, A2, A3};
|
||||||
|
|
||||||
|
int mapValue;
|
||||||
|
String reference[] = {"L","H","R"};
|
||||||
|
String finalReadable;
|
||||||
|
String final;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
BigNumber::begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
String compression(int values[]) {
|
||||||
|
String combinedInt = "";
|
||||||
|
String header = "";
|
||||||
|
for (i = 0; i < numberOfSensors; i++) {
|
||||||
|
if(values[i] < 10) {
|
||||||
|
if(values[i] < 0) {
|
||||||
|
header += String(i) + ",";
|
||||||
|
combinedInt += String(values[i] * -1);
|
||||||
|
} else {
|
||||||
|
combinedInt += "0" + String(values[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
combinedInt += String(values[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return header.substring(0,header.length()-1) + "." + combinedInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
finalReadable = "";
|
||||||
|
final = "";
|
||||||
|
int dataValues[] = {32, 62, 10, 7, -45, 91, -95, 27, 54, 50, 67, 84, 92,
|
||||||
|
68, 10, 53, 79, 65, 06, 62, 60, -15, 52, 63, 71, 9,
|
||||||
|
52, -86, 68, 52, 96, 30, 31, 50, 24, 56, -61, 54, 40, 26,
|
||||||
|
33, 34, 32, 28, 2, 96, 3, 77, 66, 97};
|
||||||
|
Serial.println(compression(dataValues));
|
||||||
|
delay(250);
|
||||||
|
}
|
||||||
88
Arduino/CompressionTest2/CompressionTest2.ino
Normal file
88
Arduino/CompressionTest2/CompressionTest2.ino
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include <bcconfig.h>
|
||||||
|
#include <BigNumber.h>
|
||||||
|
#include <number.h>
|
||||||
|
|
||||||
|
#define numberOfSensors 50
|
||||||
|
int flexSensorPins[] = {A0, A1, A2, A3};
|
||||||
|
|
||||||
|
int mapValue;
|
||||||
|
String reference[] = {"L","H"};
|
||||||
|
String finalReadable;
|
||||||
|
String final;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
BigNumber::begin();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
String toBinary(String intString, int len) {
|
||||||
|
String binary = "";
|
||||||
|
char s[len];
|
||||||
|
intString.toCharArray(s, len);
|
||||||
|
BigNumber lrgInt(s);
|
||||||
|
BigNumber two = 2;
|
||||||
|
BigNumber zero = 0;
|
||||||
|
int remainder;
|
||||||
|
|
||||||
|
while (lrgInt > zero) {
|
||||||
|
remainder = lrgInt % two;
|
||||||
|
lrgInt = lrgInt / two;
|
||||||
|
lrgInt = lrgInt - lrgInt % lrgInt
|
||||||
|
lrgInt
|
||||||
|
binary = String(remainder) + binary;
|
||||||
|
Serial.println(binary);
|
||||||
|
}
|
||||||
|
return binary;
|
||||||
|
}
|
||||||
|
|
||||||
|
String compression(int values[]) {
|
||||||
|
String finalCompress = "";
|
||||||
|
String combinedInt = "";
|
||||||
|
String binString = "";
|
||||||
|
char* s;
|
||||||
|
int counter = 0;
|
||||||
|
int change = 0;
|
||||||
|
for (i = 0; i < numberOfSensors; i++) {
|
||||||
|
if(String(values[i]).length() < 2) {
|
||||||
|
combinedInt += "0" + String(values[i]);
|
||||||
|
} else {
|
||||||
|
combinedInt += String(values[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binString = toBinary(combinedInt, combinedInt.length());
|
||||||
|
|
||||||
|
for (i = 0; i <= binString.length(); i++) {
|
||||||
|
if (binString.charAt(i) == binString.charAt(change)) {
|
||||||
|
counter += 1;
|
||||||
|
} else {
|
||||||
|
if(counter == 1) {
|
||||||
|
finalCompress = finalCompress + reference[String(binString.charAt(0)).toInt()];
|
||||||
|
} else {
|
||||||
|
finalCompress = finalCompress + String(counter) + reference[String(binString.charAt(0)).toInt()];
|
||||||
|
}
|
||||||
|
change = i;
|
||||||
|
counter = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return finalCompress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
finalReadable = "";
|
||||||
|
final = "";
|
||||||
|
int dataValues[] = {32, 62, 10, 7, 45, 91, 95, 27, 54, 50, 67, 84, 92, 68, 10,
|
||||||
|
53, 79, 65, 6, 62, 60, 15, 52, 63, 71, 9, 52, 86,
|
||||||
|
68, 52, 96, 30, 31, 50, 24, 56, 61, 54, 40, 26,
|
||||||
|
33, 34, 32, 28, 2, 96, 3, 77, 66, 97};
|
||||||
|
|
||||||
|
//for(int i = 0; i < numberOfSensors; i++) {
|
||||||
|
//mapValue = map(analogRead(flexSensorPins[i]), 512, 853, 0, 180) - 25;
|
||||||
|
//finalReadable = finalReadable + String(mapValue) + ",";
|
||||||
|
//dataValues[i] = mapValue;
|
||||||
|
String hello = compression(dataValues);
|
||||||
|
//Serial.println(hello);
|
||||||
|
delay(250);
|
||||||
|
}
|
||||||
46
Arduino/FlexTest/FlexTest.ino
Normal file
46
Arduino/FlexTest/FlexTest.ino
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#define numberOfSensors 3
|
||||||
|
int muxPins[] = {5,6,7};
|
||||||
|
int dataPin = A0;
|
||||||
|
int lastDataValues[] = {0,0,0};
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
String delLast(String input) {
|
||||||
|
return input.substring(0,input.length()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
for(i = 0; i < sizeof(muxPins); i++) {
|
||||||
|
pinMode(muxPins[i],OUTPUT);
|
||||||
|
digitalWrite(muxPins[i],LOW);
|
||||||
|
}
|
||||||
|
pinMode(dataPin, INPUT);
|
||||||
|
Serial.begin(115200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
digitalWrite(5,LOW);digitalWrite(6,LOW);digitalWrite(7,HIGH);
|
||||||
|
String finalShort = "";
|
||||||
|
String finalReal = "";
|
||||||
|
String raw = "";
|
||||||
|
int mapValue = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < numberOfSensors; i++) {
|
||||||
|
String bin = String(i,BIN);
|
||||||
|
while(bin.length() < 3) {
|
||||||
|
bin = "0" + bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j = 0; j < 3; j++) {
|
||||||
|
digitalWrite(muxPins[j],bin.substring(bin.length()-j-1,bin.length()-j).toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
mapValue = map(analogRead(dataPin), 530, 810, 0, 180);
|
||||||
|
finalShort = finalShort + String(mapValue - lastDataValues[i]) + ",";
|
||||||
|
finalReal = finalReal + String(mapValue) + ",";
|
||||||
|
raw = raw + String(analogRead(dataPin)) + ",";
|
||||||
|
lastDataValues[i] = mapValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println(delLast(raw) + " :: " + delLast(finalReal) + " :: " + delLast(finalShort));
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
192
Arduino/MPU6050_Multi/MPU6050_Multi.ino
Normal file
192
Arduino/MPU6050_Multi/MPU6050_Multi.ino
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0)
|
||||||
|
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
|
||||||
|
// is used in I2Cdev.h
|
||||||
|
#include "Wire.h"
|
||||||
|
/* I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
|
||||||
|
* for both classes must be in the include path of your project
|
||||||
|
*/
|
||||||
|
#include "I2Cdev.h"
|
||||||
|
#include "MPU6050_6Axis_MotionApps20.h"
|
||||||
|
|
||||||
|
#define NUMBER_OF_SENSORS 3 //// YOU MAY NEED TO CHANGE THIS
|
||||||
|
|
||||||
|
// Default I2C address is 0x68
|
||||||
|
// AD0 LOW(0) = 0x68 (Default for SparkFun breakout and InvenSense evaluation board)
|
||||||
|
// AD0 HIGH(1) = 0x69
|
||||||
|
|
||||||
|
// MPU Control Variables
|
||||||
|
MPU6050 mpu;
|
||||||
|
bool dmpReady; // Set true if DMP init was successful.
|
||||||
|
uint8_t devStatus; // Return status after each device operation. (0 = success, !0 = error)
|
||||||
|
uint8_t mpuIntStatus; // Holds interrupt status byte from MPU.
|
||||||
|
uint16_t packetSize; // Expected DMP packet size. (Default is 42 bytes)
|
||||||
|
uint16_t fifoCount; // Count of all bytes currently in FIFO.
|
||||||
|
uint8_t fifoBuffer[64]; // FIFO storage buffer.
|
||||||
|
|
||||||
|
// Orientation and Motion Variables
|
||||||
|
Quaternion q; // [W, X, Y, Z] Quaternion container.
|
||||||
|
VectorFloat gravity; // [X, Y, Z] Gravity vector
|
||||||
|
float ypr[3]; // [Yaw, Pitch, Roll] array container.
|
||||||
|
|
||||||
|
//Digital Pins Reference Variables
|
||||||
|
const int latchPin = 2; //ST_CP or RCLK
|
||||||
|
const int clockPin = 1; //SH_CP or SRCLK
|
||||||
|
const int dataPin = 3; //DS or SER
|
||||||
|
|
||||||
|
// Other Variables
|
||||||
|
String finalParts[NUMBER_OF_SENSORS];
|
||||||
|
String final = "";
|
||||||
|
|
||||||
|
//==============================================================
|
||||||
|
|
||||||
|
void switchSensor(int sensorNumber) {
|
||||||
|
/* The shift register shifts out bits to the ADO lines. In binary:
|
||||||
|
* 0001 = Sensor on Q0(QA) 2^0 = 1 = 0001 in binary
|
||||||
|
* 0010 = Sensor on Q1(QB) 2^1 = 2 = 0010 in binary
|
||||||
|
*/
|
||||||
|
int data = (int) 1 << (sensorNumber - 1); // Shift register serial data input.
|
||||||
|
|
||||||
|
digitalWrite(latchPin, LOW); // Hold low for as long as you are transmitting data.
|
||||||
|
shiftOutBits(dataPin, clockPin, ~data); // Shift out the bits into the shift register; negate data. (0001 = 1000)
|
||||||
|
digitalWrite(latchPin, HIGH); // Ends transmission of data.
|
||||||
|
}
|
||||||
|
|
||||||
|
void shiftOutBits(int myDataPin, int myClockPin, byte myDataOut) {
|
||||||
|
// This shifts 8 bits out MSB first.
|
||||||
|
|
||||||
|
//Function Setup
|
||||||
|
int l = 0;
|
||||||
|
int pinState;
|
||||||
|
|
||||||
|
pinMode(myClockPin, OUTPUT);
|
||||||
|
pinMode(myDataPin, OUTPUT);
|
||||||
|
|
||||||
|
// Clear everything out in case to prepare shift register.
|
||||||
|
digitalWrite(myDataPin, 0);
|
||||||
|
digitalWrite(myClockPin, 0);
|
||||||
|
|
||||||
|
// For each bit in the byte myDataOut.
|
||||||
|
for (l = 7; l >= 0; l--) {
|
||||||
|
digitalWrite(myClockPin, 0);
|
||||||
|
|
||||||
|
//if the value passed to myDataOut and a bitmask result
|
||||||
|
// true then... so if we are at i=6 and our value is
|
||||||
|
// %11010100 it would the code compares it to %01000000
|
||||||
|
// and proceeds to set pinState to 1.
|
||||||
|
if ( myDataOut & (1 << l) ) {
|
||||||
|
pinState = 1;
|
||||||
|
//////Serial.print(pinState);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pinState = 0;
|
||||||
|
//////Serial.print(pinState);
|
||||||
|
}
|
||||||
|
// Sets the pin to HIGH or LOW depending on pinState.
|
||||||
|
digitalWrite(myDataPin, pinState);
|
||||||
|
// Register shifts on HIGH of myClockPin.
|
||||||
|
digitalWrite(myClockPin, 1);
|
||||||
|
// Stop sending on myDataPin.
|
||||||
|
digitalWrite(myDataPin, 0);
|
||||||
|
}
|
||||||
|
// Stop shifting.
|
||||||
|
digitalWrite(myClockPin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================================================
|
||||||
|
// === MAIN PROGRAM SETUP ===
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
delay(2000);
|
||||||
|
|
||||||
|
Wire.begin(); // Join I2C bus. (I2Cdev library doesn't do this automatically.)
|
||||||
|
TWBR = 24; // Sets frequency of the clock (SCL) higher.
|
||||||
|
|
||||||
|
|
||||||
|
Serial.begin(115200); // Initialize serial communication with baud rate.
|
||||||
|
|
||||||
|
pinMode(latchPin, OUTPUT); // Tell the Arduino to send or recieve signals.
|
||||||
|
|
||||||
|
int dmpReadyCounter = 0; // Counts number of sensors ready.
|
||||||
|
|
||||||
|
for (int i = 1; i <= NUMBER_OF_SENSORS; i++) {
|
||||||
|
/* We read data from all sensors by switching addresses one by one, only reading from the first address (0x68).
|
||||||
|
* Therefore, we shift the addresses to the next sensor, and retrieve its value.
|
||||||
|
*/
|
||||||
|
switchSensor(i);
|
||||||
|
|
||||||
|
mpu.initialize(); // Intialize device.
|
||||||
|
|
||||||
|
devStatus = mpu.dmpInitialize(); // Load and configure the DMP. (Digital Motion Processor)
|
||||||
|
|
||||||
|
// Gyroscope offsets. (Change if necessary)
|
||||||
|
mpu.setXGyroOffset(220);
|
||||||
|
mpu.setYGyroOffset(76);
|
||||||
|
mpu.setZGyroOffset(-85);
|
||||||
|
mpu.setZAccelOffset(1788);
|
||||||
|
|
||||||
|
// Check success of DMP.
|
||||||
|
if (devStatus == 0) {
|
||||||
|
mpu.setDMPEnabled(true);
|
||||||
|
|
||||||
|
dmpReadyCounter += 1; // Add one to count number of ready sensors.
|
||||||
|
|
||||||
|
packetSize = mpu.dmpGetFIFOPacketSize(); // Get expected DMP packet size for later comparison
|
||||||
|
} else {
|
||||||
|
// Error!
|
||||||
|
Serial.print("Error on sensor " + String(i) + "\n");
|
||||||
|
}
|
||||||
|
/////////Serial.print(String(digitalRead(8)) + String(digitalRead(9)) + String(digitalRead(10)) + String(digitalRead(11)) + "\n");
|
||||||
|
}
|
||||||
|
if (dmpReadyCounter == 3) {
|
||||||
|
dmpReady = true; // Set DMP Ready flag. (Allows main loop to use the DMP.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================================================
|
||||||
|
// === MAIN PROGRAM LOOP ===
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
final = ""; // Reset final to nothing.
|
||||||
|
// If DMP isn't ready...
|
||||||
|
if (!(dmpReady)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 1; k <= NUMBER_OF_SENSORS; k++) {
|
||||||
|
|
||||||
|
switchSensor(k);
|
||||||
|
|
||||||
|
// Check for overflow.
|
||||||
|
if (fifoCount == 1024) {
|
||||||
|
mpu.resetFIFO(); // Reset so we can continue cleanly.
|
||||||
|
} else {
|
||||||
|
fifoCount = mpu.getFIFOCount(); // Get current FIFO count.
|
||||||
|
|
||||||
|
// Wait for correct avaliable data length.
|
||||||
|
while (fifoCount < packetSize) {
|
||||||
|
fifoCount = mpu.getFIFOCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
mpu.getFIFOBytes(fifoBuffer, packetSize); // Read a packet from FIFO
|
||||||
|
/* Track FIFO count in case there is more than 1 packet avaliable.
|
||||||
|
* (Read more without waiting for an interrupt.)
|
||||||
|
*/
|
||||||
|
fifoCount -= packetSize;
|
||||||
|
|
||||||
|
// Get values to process.
|
||||||
|
mpu.dmpGetQuaternion(&q, fifoBuffer);
|
||||||
|
mpu.dmpGetGravity(&gravity, &q);
|
||||||
|
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
|
||||||
|
|
||||||
|
// Concatenate for outputting. (Displays in Euler Angles in degrees.)
|
||||||
|
finalParts[k - 1] = String(ypr[0] * 180 / M_PI) + "," + String(ypr[1] * 180 / M_PI) + "," + String(ypr[2] * 180 / M_PI) + ":";
|
||||||
|
final += finalParts[k - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.print(final);
|
||||||
|
Serial.print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
30
Arduino/MUXTest/MUXTest.ino
Normal file
30
Arduino/MUXTest/MUXTest.ino
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
int muxPins[3] = {5,6,7};
|
||||||
|
int dataPin = 13;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
for(int i = 0; i < 3; i++) {
|
||||||
|
pinMode(muxPins[i],OUTPUT);
|
||||||
|
digitalWrite(muxPins[i],LOW);
|
||||||
|
}
|
||||||
|
pinMode(dataPin, OUTPUT);
|
||||||
|
digitalWrite(dataPin,HIGH);
|
||||||
|
Serial.begin(115200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
for(int i = 0; i < 8; i++) {
|
||||||
|
String bin = String(i,BIN);
|
||||||
|
while(bin.length() < 3) {
|
||||||
|
bin = "0" + bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j = 0; j < 3; j++) {
|
||||||
|
digitalWrite(muxPins[j],bin.substring(bin.length()-j-1,bin.length()-j).toInt());
|
||||||
|
}
|
||||||
|
Serial.println(" ");
|
||||||
|
delay(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
// put your main code here, to run repeatedly:
|
||||||
|
|
||||||
|
}
|
||||||
75
Arduino/MotorTest/MotorTest.ino
Normal file
75
Arduino/MotorTest/MotorTest.ino
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
int inA1 = 8; // wire 1 (blue)
|
||||||
|
int inA2 = 9; // wire 2 (pink)
|
||||||
|
int inB1 = 10; // wire 3 (yellow)
|
||||||
|
int inB2 = 11; // wire 4 (orange)
|
||||||
|
int counter = 0;
|
||||||
|
//wire 5 (Red) is a VCC and should be put to 5V, with this setup it is not needed, but it is good to know if you make something like an 8 step spinup
|
||||||
|
|
||||||
|
int stepDelay = 2;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(inA1, OUTPUT);
|
||||||
|
pinMode(inA2, OUTPUT);
|
||||||
|
pinMode(inB1, OUTPUT);
|
||||||
|
pinMode(inB2, OUTPUT);
|
||||||
|
pinMode(A1,INPUT);
|
||||||
|
}
|
||||||
|
void loop(){
|
||||||
|
|
||||||
|
Serial.println(String(analogRead(A1)));
|
||||||
|
Serial.println("hi");
|
||||||
|
/*for(int i =0;i<1600;i++) {
|
||||||
|
step1();
|
||||||
|
step2();
|
||||||
|
step3();
|
||||||
|
step4();
|
||||||
|
}
|
||||||
|
stopMotor();
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
for(int j=0;j<1600;j++) {
|
||||||
|
step3();
|
||||||
|
step2();
|
||||||
|
step1();
|
||||||
|
step4();
|
||||||
|
}
|
||||||
|
stopMotor();
|
||||||
|
delay(500);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void step1() {
|
||||||
|
digitalWrite(inA1, LOW);
|
||||||
|
digitalWrite(inA2, HIGH);
|
||||||
|
digitalWrite(inB1, HIGH);
|
||||||
|
digitalWrite(inB2, LOW);
|
||||||
|
delay(stepDelay);
|
||||||
|
|
||||||
|
}
|
||||||
|
void step2() {
|
||||||
|
digitalWrite(inA1, LOW);
|
||||||
|
digitalWrite(inA2, HIGH);
|
||||||
|
digitalWrite(inB1, LOW);
|
||||||
|
digitalWrite(inB2, HIGH);
|
||||||
|
delay(stepDelay);
|
||||||
|
}
|
||||||
|
void step3() {
|
||||||
|
digitalWrite(inA1, HIGH);
|
||||||
|
digitalWrite(inA2, LOW);
|
||||||
|
digitalWrite(inB1, LOW);
|
||||||
|
digitalWrite(inB2, HIGH);
|
||||||
|
delay(stepDelay);
|
||||||
|
}
|
||||||
|
void step4() {
|
||||||
|
digitalWrite(inA1, HIGH);
|
||||||
|
digitalWrite(inA2, LOW);
|
||||||
|
digitalWrite(inB1, HIGH);
|
||||||
|
digitalWrite(inB2, LOW);
|
||||||
|
delay(stepDelay);
|
||||||
|
}
|
||||||
|
void stopMotor() {
|
||||||
|
digitalWrite(inA1, LOW);
|
||||||
|
digitalWrite(inA2, LOW);
|
||||||
|
digitalWrite(inB1, LOW);
|
||||||
|
digitalWrite(inB2, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
67
Arduino/SevenSegmentLED/SevenSegmentLED.ino
Normal file
67
Arduino/SevenSegmentLED/SevenSegmentLED.ino
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
const int latchPin = 8; //ST_CP or RCLK
|
||||||
|
const int clockPin = 12; //SH_CP or SRCLK
|
||||||
|
const int dataPin = 11; //DS or SER
|
||||||
|
|
||||||
|
byte seven_seg_digits[10][7] = {
|
||||||
|
{ 1,1,1,1,1,1,0 }, // = 0
|
||||||
|
{ 0,1,1,0,0,0,0 }, // = 1
|
||||||
|
{ 1,1,0,1,1,0,1 }, // = 2
|
||||||
|
{ 1,1,1,1,0,0,1 }, // = 3
|
||||||
|
{ 0,1,1,0,0,1,1 }, // = 4
|
||||||
|
{ 1,0,1,1,0,1,1 }, // = 5
|
||||||
|
{ 1,0,1,1,1,1,1 }, // = 6
|
||||||
|
{ 1,1,1,0,0,0,0 }, // = 7
|
||||||
|
{ 1,1,1,1,1,1,1 }, // = 8
|
||||||
|
{ 1,1,1,0,0,1,1 } // = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
int digits[10] = {
|
||||||
|
126, 48, 109, 121, 51, 91, 95, 112, 127,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void writeNumber(int character) {
|
||||||
|
/* The shift register shifts out bits to the ADO lines. In binary:
|
||||||
|
* 1110 = Sensor on Q0(QA) ~(2^0) = ~1 = 1110 in binary
|
||||||
|
* 1101 = Sensor on Q1(QB) ~(2^1) = ~2 = 1101 in binary
|
||||||
|
* '~' = not
|
||||||
|
*/
|
||||||
|
//int data = (int) 1 << (sensorNumber - 1); // Shift register serial data input.
|
||||||
|
|
||||||
|
digitalWrite(latchPin, LOW); // Hold low for as long as you are transmitting data.
|
||||||
|
shiftOutBits(dataPin, clockPin, character); // Shift out the bits into the shift register; negate data. (0001 = 1000)
|
||||||
|
digitalWrite(latchPin, HIGH); // Ends transmission of data.
|
||||||
|
}
|
||||||
|
|
||||||
|
void shiftOutBits(int myDataPin, int myClockPin, int number) {
|
||||||
|
// This shifts 8 bits out MSB first.
|
||||||
|
|
||||||
|
// Setup Varaibles
|
||||||
|
int pinState;
|
||||||
|
|
||||||
|
pinMode(myClockPin, OUTPUT);
|
||||||
|
pinMode(myDataPin, OUTPUT);
|
||||||
|
|
||||||
|
// Clear everything out in case to prepare shift register.
|
||||||
|
digitalWrite(myDataPin, 0);
|
||||||
|
digitalWrite(myClockPin, 0);
|
||||||
|
|
||||||
|
// For each bit in the byte myDataOut.
|
||||||
|
for (int i = 7; i >= 0; i--) {
|
||||||
|
digitalWrite(myClockPin, 0);
|
||||||
|
|
||||||
|
pinState = 1 - seven_seg_digits[number][i];
|
||||||
|
digitalWrite(myDataPin, pinState); // Sets the pin to HIGH or LOW depending on pinState.
|
||||||
|
digitalWrite(myClockPin, 1); // Register shifts on HIGH of myClockPin.
|
||||||
|
digitalWrite(myDataPin, 0); // Stop sending on myDataPin.
|
||||||
|
}
|
||||||
|
digitalWrite(myClockPin, 0); // Stop shifting.
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
writeNumber(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
54
Arduino/Transfer.py
Normal file
54
Arduino/Transfer.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import serial
|
||||||
|
port = serial.Serial('COM6', 9600)
|
||||||
|
valuesBeforeAveraging = 6
|
||||||
|
numberOfSensors = 3
|
||||||
|
splitValues = []
|
||||||
|
averageSetLength = 0
|
||||||
|
nan = ['nan','na']
|
||||||
|
|
||||||
|
def getNewValue():
|
||||||
|
newRead = port.readline()[:-2].lower()
|
||||||
|
if nan[0] in newRead or nan[1] in newRead:
|
||||||
|
print "FIFO Buffer Overflow"
|
||||||
|
getNewValue()
|
||||||
|
else:
|
||||||
|
return newRead
|
||||||
|
|
||||||
|
def getNewAverage(newValue):
|
||||||
|
global splitValues
|
||||||
|
global averageSetLength
|
||||||
|
average = 0.0000
|
||||||
|
outputLine = ""
|
||||||
|
|
||||||
|
splitValues.append([]) # Append new trial
|
||||||
|
|
||||||
|
if averageSetLength > valuesBeforeAveraging:
|
||||||
|
del splitValues[0]
|
||||||
|
|
||||||
|
averageSetLength = len(splitValues)
|
||||||
|
|
||||||
|
for yprNum, ypr in enumerate(newValue.split(":")): # For each sensor/YPR set
|
||||||
|
splitValues[averageSetLength - 1].append([]) # Append new array, compensate for array start 0
|
||||||
|
|
||||||
|
for valueNum, value in enumerate(ypr.split(",")): # For each value in YPR set
|
||||||
|
splitValues[averageSetLength - 1][yprNum].append(float(value)) # Append value to array
|
||||||
|
|
||||||
|
for entryNum in xrange(0, averageSetLength): #For all trials
|
||||||
|
average += splitValues[entryNum][yprNum][valueNum] # Add all x,y,z values
|
||||||
|
average = average / (averageSetLength) # Divide by number of trials
|
||||||
|
outputLine = outputLine + str(average)[:str(average).find('.') + 4] + ","
|
||||||
|
average = 0.0000
|
||||||
|
outputLine = outputLine[:-1] + ":"
|
||||||
|
outputLine = outputLine[:-1]
|
||||||
|
|
||||||
|
return outputLine
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
try:
|
||||||
|
newRead = getNewValue()
|
||||||
|
final = getNewAverage(newRead)
|
||||||
|
print final
|
||||||
|
file = open('Transfer.txt','w')
|
||||||
|
file.write(final)
|
||||||
|
file.close()
|
||||||
|
except: IOError
|
||||||
86
Arduino/shiftOutTest/shiftOutTest.ino
Normal file
86
Arduino/shiftOutTest/shiftOutTest.ino
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
//**************************************************************//
|
||||||
|
// Name : shiftOutCode, Dual Binary Counters //
|
||||||
|
// Author : Carlyn Maw, Tom Igoe //
|
||||||
|
// Date : 25 Oct, 2006 //
|
||||||
|
// Version : 1.0 //
|
||||||
|
// Notes : Code for using a 74HC595 Shift Register //
|
||||||
|
// : to count from 0 to 255 //
|
||||||
|
//**************************************************************//
|
||||||
|
|
||||||
|
//Pin connected to ST_CP of 74HC595
|
||||||
|
int latchPin = 2;
|
||||||
|
//Pin connected to SH_CP of 74HC595
|
||||||
|
int clockPin = 1;
|
||||||
|
////Pin connected to DS of 74HC595
|
||||||
|
int dataPin = 3;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
//Start Serial for debuging purposes
|
||||||
|
Serial.begin(9600);
|
||||||
|
//set pins to output because they are addressed in the main loop
|
||||||
|
pinMode(latchPin, OUTPUT);
|
||||||
|
digitalWrite(5, LOW);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
//count up routine
|
||||||
|
//ground latchPin and hold low for as long as you are transmitting
|
||||||
|
digitalWrite(latchPin, 0);
|
||||||
|
//count down on RED LEDs
|
||||||
|
shiftOut(dataPin, clockPin, 2);
|
||||||
|
//return the latch pin high to signal chip that it
|
||||||
|
//no longer needs to listen for information
|
||||||
|
digitalWrite(latchPin, 1);
|
||||||
|
delay(1000);
|
||||||
|
Serial.print(String(digitalRead(8)) + String(digitalRead(9)) + String(digitalRead(10)) + String(digitalRead(11)) + "\n");
|
||||||
|
//Serial.print(digitalRead(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
|
||||||
|
// This shifts 8 bits out MSB first,
|
||||||
|
//on the rising edge of the clock,
|
||||||
|
//clock idles low
|
||||||
|
|
||||||
|
//internal function setup
|
||||||
|
int i=0;
|
||||||
|
int pinState;
|
||||||
|
pinMode(myClockPin, OUTPUT);
|
||||||
|
pinMode(myDataPin, OUTPUT);
|
||||||
|
|
||||||
|
//clear everything out just in case to
|
||||||
|
//prepare shift register for bit shifting
|
||||||
|
digitalWrite(myDataPin, 0);
|
||||||
|
digitalWrite(myClockPin, 0);
|
||||||
|
|
||||||
|
//for each bit in the byte myDataOut<75>
|
||||||
|
//NOTICE THAT WE ARE COUNTING DOWN in our for loop
|
||||||
|
//This means that %00000001 or "1" will go through such
|
||||||
|
//that it will be pin Q0 that lights.
|
||||||
|
for (i=7; i>=0; i--) {
|
||||||
|
digitalWrite(myClockPin, 0);
|
||||||
|
|
||||||
|
//if the value passed to myDataOut and a bitmask result
|
||||||
|
// true then... so if we are at i=6 and our value is
|
||||||
|
// %11010100 it would the code compares it to %01000000
|
||||||
|
// and proceeds to set pinState to 1.
|
||||||
|
if ( myDataOut & (1<<i) ) {
|
||||||
|
pinState= 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pinState= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Sets the pin to HIGH or LOW depending on pinState
|
||||||
|
digitalWrite(myDataPin, pinState);
|
||||||
|
//register shifts bits on upstroke of clock pin
|
||||||
|
digitalWrite(myClockPin, 1);
|
||||||
|
//zero the data pin after shift to prevent bleed through
|
||||||
|
digitalWrite(myDataPin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//stop shifting
|
||||||
|
digitalWrite(myClockPin, 0);
|
||||||
|
}
|
||||||
BIN
Compression/3DBlocks.png
Normal file
BIN
Compression/3DBlocks.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
BIN
Compression/4DBlocks.png
Normal file
BIN
Compression/4DBlocks.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
125
Compression/Algorithm Details.tex
Normal file
125
Compression/Algorithm Details.tex
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
\documentclass{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[margin=1in]{geometry}
|
||||||
|
\usepackage{amsfonts, amsmath, amssymb}
|
||||||
|
\usepackage[none]{hyphenat}
|
||||||
|
\usepackage{fancyhdr}
|
||||||
|
\usepackage{titling}
|
||||||
|
\usepackage{changepage}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\usepackage{wrapfig}
|
||||||
|
|
||||||
|
\renewcommand\maketitlehooka{\null\mbox{}\vfill}
|
||||||
|
\renewcommand\maketitlehookd{\vfill\null}
|
||||||
|
|
||||||
|
\pagestyle{fancy}
|
||||||
|
\fancyhead[L]{\slshape Algorithm Details}
|
||||||
|
\fancyhead[R]{Kenneth Jao}
|
||||||
|
\fancyfoot[C]{\thepage}
|
||||||
|
|
||||||
|
\title{Lossy Compression through Multi-dimensional Fourier Transforms }
|
||||||
|
\author{Kenneth Jao}
|
||||||
|
\date{February 2019}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\pagebreak
|
||||||
|
|
||||||
|
\section{Introduction}
|
||||||
|
This document covers the details of the mathematics of the compression algorithm. Each main mathematical application will be explained in detail. Firstly an overview of the algorithm as a whole will be given.
|
||||||
|
|
||||||
|
\subsection{Notation}
|
||||||
|
\begin{adjustwidth}{.5in}{}
|
||||||
|
Data Matrix: \[ \left[ {\begin{array}{cccc} A & B & C & \dots \end{array}} \right] or \left[\ A,\ B,\ C,\ \dots \ \right]\]
|
||||||
|
Will mean that the dimensions 0, 1, 2, \dots will correspond to A, B, C, \dots and represents an array of data, not a mathematical matrix.\\
|
||||||
|
\newline
|
||||||
|
N-Dimensional Polynomial:\\
|
||||||
|
\begin{adjustwidth}{.5in}{}
|
||||||
|
$\vec{e_i}=(e_1,\ e_2,\ e_3, \dots e_n) \in \mathbb{N}^n$ will represent the i-th permutation of $\vec{e}$.\\
|
||||||
|
$\vec{x}^{\vec{e}} = x_1^{e_1}\cdot x_2^{e_2}\cdot \dots x_n^{e_n}$ where $\vec{x}=(x_1,\ x_2,\ x_3, \dots x_n) \in \mathbb{R}^n$\\
|
||||||
|
An arbitrary n-dimensional polynomial of degree m $P(\ x_1,\ x_2,\ x_3,\dots,\ x_n)$ will equal: \[ a_1x^{\vec{e_1}} + a_2x^{\vec{e_2}} + a_3x^{\vec{e_3}} + \dots + a_{max}x^{\vec{e_{max}}}\]
|
||||||
|
Where $max=(m+1)^n$
|
||||||
|
\end{adjustwidth}
|
||||||
|
|
||||||
|
\end{adjustwidth}
|
||||||
|
|
||||||
|
\subsection{Algorithm Overview}
|
||||||
|
|
||||||
|
\begin{adjustwidth}{.5in}{}
|
||||||
|
A set of video data in given in the format: \[ \left[ {\begin{array}{cccc} Frame & Y Pixel & X Pixel & RGB \end{array}} \right] \]
|
||||||
|
After receiving this video data, it will be processed into square blocks of dimension $N$, denoted by $Block_{w_1,w_2,w_3,...}$ where ${w_1, w_2, w_3,...}$ represents the sorting of $N$ dimensional blocks in a format that correspond to the location of the data in the ordered video. For instance, given a data in format $[\ x,\ y,\ z\ ]$, square blocks of dimension $N$ can be extracted such that the new data structure is now in the form $[\frac{x}{N},\frac{y}{N},\frac{z}{N}, N, N, N]$, and thus, in this case, $w_1 = \frac{x}{N},\ w_2 = \frac{y}{N},\ w_3 = \frac{z}{N}$. Afterwards, there are two possible steps.
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item The first option is to purely fit a polynomial to the data of each block. That is, find a polynomial of degree $N-1$ and of dimension $N$ where each $Block_{w_1,w_2,w_3,...}[\ x_1,\ x_2,\ x_3,\ \dots \ ]$ will correspond to some $P(\ x_1,\ x_2,\ x_3,\ \dots,\ x_n)$. The output will be the coefficients of the new polynomial.
|
||||||
|
\item The second option is to attempt to create a polynomial of degree $N-1$ and of dimension $N$ where its coefficients match first $N$ terms of the Taylor Polynomial of $cos(x_1+x_2+x_3+\dots +x_n)$. The coefficients of the new polynomial will attempt to as close to the Taylor Polynomial. The output will be the coefficients of the new polynomial along with a separate function, its usage explained later in the methodology.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\noindent An $N$ dimensional Discrete Fourier Transform (DFT) will now be performed on these blocks. The output is the first $k$ coefficients, where $k$ is determined when the sum of a sufficient $k$ coefficients is greater than 90\% of the convergence of the $N$ dimensional Fourier Series. The 'first' components will be determined by a counting method discussed later.\\
|
||||||
|
\newline
|
||||||
|
Now, these coefficients corresponding to each $Block_{w_1,w_2,w_3,...}$ will be flattened to 2 dimensions. A Discrete Cosine Transform (DCT) will now be applied onto these coefficients, with the rounding threshold higher, for the sake of precision on coefficients.\\
|
||||||
|
\newline
|
||||||
|
The algorithm is now complete. The final products will include: a 2 dimensional DCT of the coefficients of an $N$ dimensional DFT, function for each block. The raveling process will be standard for a given dimensional size, so this needs not be stored.
|
||||||
|
\end{adjustwidth}
|
||||||
|
|
||||||
|
\pagebreak
|
||||||
|
|
||||||
|
\section{Changing Dimensions}
|
||||||
|
|
||||||
|
Firstly, the video is turned into a basic 3 dimensions. This is done by stacking the Frame and RGB dimensions and swapping the Y Pixel and X Pixel to make it more intuitively oriented. The new form becomes: \[ \left[ {\begin{array}{ccc} X Pixel & Y Pixel & Frame+RGB \end{array}} \right] \]
|
||||||
|
That is to say, $[\ x,\ y,\ 3f\ ]$, $[\ x,\ y,\ 3f+1\ ]$, $[\ x,\ y,\ 3f+2\ ]$ would lie in frame $f$, and represent the R, G, and B values, respectively. From here, we can start slicing the data in certain ways to obtain our desired block dimension.
|
||||||
|
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=2in]{images/RGB.png}
|
||||||
|
\caption{Visualization of flattened video data.}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsection{3-Dimensional Block}
|
||||||
|
|
||||||
|
\begin{adjustwidth}{.5in}{}
|
||||||
|
To obtain 3-Dimensional blocks, in this case, we simply can just extract cubes from the already flattened video data. (See Figure 2.) This arises in a data format of $[\frac{x}{N},\frac{y}{N},\frac{z}{N}, N, N, N]$. In this algorithm, $N=6$ was chosen.
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=3in]{images/3DBlocks.png}
|
||||||
|
\caption{3D Blocked Video Data}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\end{adjustwidth}
|
||||||
|
|
||||||
|
\subsection{4-Dimensional Block}
|
||||||
|
To obtain 4-Dimensional blocks, in this case, we extract a $NxNxN$ cube and then take $N$ cubes downward. (See Figure 3.) This arises in a data format of $[\frac{x}{N},\frac{y}{N^2},\frac{z}{N}, N, N, N, N]$. In this algorithm, $N=6$ was chosen.
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=3in]{images/4DBlocks.png}
|
||||||
|
\caption{4D Blocked Video Data}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\section{Polynomial Fitting}
|
||||||
|
There are two potential outputs of polynomial fitting. FINISH
|
||||||
|
\subsection{Pure Polynomial Fitting}
|
||||||
|
The given data $D$ is in format: \[ \left[ \begin{array}{ccccc} x_1 & x_2 & x_3 & \dots & x_n \end{array} \right] \]
|
||||||
|
Where its size is $(m+1,\ m+1,\, m+1,\ \dots,\ m+1)$. To find an n-dimensional polynomial of degree m, all that is necessary is find a solution to this system of linear equations: \
|
||||||
|
\[ \left[ \begin{array}{ccccc}
|
||||||
|
\vec{e_1}^{\vec{e_1}} & \vec{e_1}^{\vec{e_2}} & \vec{e_1}^{\vec{e_3}} & \dots & \vec{e_1}^{\vec{e_{max}}}\\
|
||||||
|
\vec{e_2}^{\vec{e_1}} & \vec{e_2}^{\vec{e_2}} & \vec{e_2}^{\vec{e_3}} & \dots & \vec{e_2}^{\vec{e_{max}}}\\
|
||||||
|
\vec{e_3}^{\vec{e_1}} & \vec{e_3}^{\vec{e_2}} & \vec{e_3}^{\vec{e_3}} & \dots & \vec{e_3}^{\vec{e_{max}}}\\
|
||||||
|
\vdots & \vdots & \vdots & \vdots & \vdots \\
|
||||||
|
\vec{e_{max}}^{\vec{e_1}} & \vec{e_{max}}^{\vec{e_2}} & \vec{e_{max}}^{\vec{e_3}} & \dots & \vec{e_{max}}^{\vec{e_{max}}}
|
||||||
|
\end{array} \right]
|
||||||
|
\left[ \begin{array}{c} a_1 \\ a_2 \\ a_3 \\ \vdots \\ a_{max} \end{array} \right] =
|
||||||
|
\left[ \begin{array}{c} D[\vec{e_1}] \\ D[\vec{e_2}] \\ D[\vec{e_3}] \\ \vdots \\ D[\vec{e_{max}}] \end{array} \right]\]
|
||||||
|
Thus, to find the coefficients, all that is necessary is to compute:
|
||||||
|
\[ {\left[ \begin{array}{ccccc}
|
||||||
|
\vec{e_1}^{\vec{e_1}} & \vec{e_1}^{\vec{e_2}} & \vec{e_1}^{\vec{e_3}} & \dots & \vec{e_1}^{\vec{e_{max}}}\\
|
||||||
|
\vec{e_2}^{\vec{e_1}} & \vec{e_2}^{\vec{e_2}} & \vec{e_2}^{\vec{e_3}} & \dots & \vec{e_2}^{\vec{e_{max}}}\\
|
||||||
|
\vec{e_3}^{\vec{e_1}} & \vec{e_3}^{\vec{e_2}} & \vec{e_3}^{\vec{e_3}} & \dots & \vec{e_3}^{\vec{e_{max}}}\\
|
||||||
|
\vdots & \vdots & \vdots & \vdots & \vdots \\
|
||||||
|
\vec{e_{max}}^{\vec{e_1}} & \vec{e_{max}}^{\vec{e_2}} & \vec{e_{max}}^{\vec{e_3}} & \dots & \vec{e_{max}}^{\vec{e_{max}}}
|
||||||
|
\end{array} \right]}^{-1}
|
||||||
|
\left[ \begin{array}{c} D[\vec{e_1}] \\ D[\vec{e_2}] \\ D[\vec{e_3}] \\ \vdots \\ D[\vec{e_{max}}] \end{array} \right]\]
|
||||||
|
|
||||||
|
\noindent Thus, $a_1,\ a_2,\ a_3, \dots,\ a_3$ has now been found.
|
||||||
|
|
||||||
|
\subsection{Cosine Taylor Polynomial Fitting}
|
||||||
|
|
||||||
|
\end{document}
|
||||||
BIN
Compression/Blocks.blend
Normal file
BIN
Compression/Blocks.blend
Normal file
Binary file not shown.
BIN
Compression/RGB.png
Normal file
BIN
Compression/RGB.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
263
Compression/compress.py
Normal file
263
Compression/compress.py
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
import math
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import cv2 as cv
|
||||||
|
import numpy as np
|
||||||
|
import scipy.linalg as spla
|
||||||
|
from functools import reduce
|
||||||
|
from os import system
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
def read_video(limit = -1):
|
||||||
|
video = []
|
||||||
|
cap = cv.VideoCapture('D:/Videos/test.mkv')
|
||||||
|
frame_num = 0
|
||||||
|
while cap.isOpened():
|
||||||
|
if limit == frame_num:
|
||||||
|
break
|
||||||
|
ret, frame = cap.read()
|
||||||
|
video.append(frame)
|
||||||
|
system('cls')
|
||||||
|
print("Loading video: {:.2f}%".format(100*frame_num/limit))
|
||||||
|
frame_num += 1
|
||||||
|
return video
|
||||||
|
|
||||||
|
def change_dimension(data, dim):
|
||||||
|
'''
|
||||||
|
Video data is in form [Frame][Y Pixel][X Pixel][RGB]
|
||||||
|
Maximum size should be 10, but smaller is better.
|
||||||
|
Eventually, all dimensional changing should be done in C, programmed
|
||||||
|
specifically for each dimension.
|
||||||
|
'''
|
||||||
|
def cubify(data, s):
|
||||||
|
c = tuple(np.array(data.shape)//s)
|
||||||
|
cubed = np.zeros(tuple(list(c)+[s]*len(c)), dtype=int)
|
||||||
|
trim = [slice(0,s)]
|
||||||
|
def permute(n, dim=[]):
|
||||||
|
if n == len(c):
|
||||||
|
slice_ind = [slice(dim[i]*s, (dim[i]+1)*s) for i in range(n)]
|
||||||
|
cubed[tuple(dim)] = data[tuple(slice_ind)]
|
||||||
|
else:
|
||||||
|
for x in range(c[n]):
|
||||||
|
permute(n+1, dim+[x])
|
||||||
|
permute(0)
|
||||||
|
|
||||||
|
return cubed
|
||||||
|
|
||||||
|
if dim not in [3,4]:
|
||||||
|
raise Exception("Not an available target dimension!")
|
||||||
|
|
||||||
|
if dim == 3:
|
||||||
|
# Outer Form: [X Block][Y Block][Z Block]
|
||||||
|
# Inner Form: [X Pixel][Y Pixel][Frame+RGB] Size: 6
|
||||||
|
s = 6
|
||||||
|
blocks = np.swapaxes(np.concatenate(data, axis=2), 0, 1)
|
||||||
|
blocks = cubify(blocks, s)
|
||||||
|
elif dim == 4:
|
||||||
|
# Outer Form [X Block][Y Block][Z Block]
|
||||||
|
# Inner Form [Psuedo-Y Block][X Pixel][Y Pizel][Frame+RGB] Size: 6
|
||||||
|
s = 6
|
||||||
|
blocks = change_dimension(data, 3)
|
||||||
|
c = list(blocks.shape)[:3]
|
||||||
|
c[2] = c[2]//s
|
||||||
|
cubed = np.zeros(tuple(c+[s]*4), dtype=int)
|
||||||
|
for x in range(c[0]):
|
||||||
|
for y in range(c[1]):
|
||||||
|
for z in range(c[2]):
|
||||||
|
arr = np.concatenate(blocks[x:x+1][0][y:y+1,s*z:s*(z+1)])
|
||||||
|
cubed[x,y,z] = arr
|
||||||
|
blocks = cubed
|
||||||
|
|
||||||
|
return blocks
|
||||||
|
|
||||||
|
def permutations(arr):
|
||||||
|
'''
|
||||||
|
The input array will carry possible permutations.
|
||||||
|
'''
|
||||||
|
final = []
|
||||||
|
def permute(n, items=[]):
|
||||||
|
if n == len(arr):
|
||||||
|
final.append(items)
|
||||||
|
else:
|
||||||
|
for x in arr[n]:
|
||||||
|
permute(n+1, items+[x])
|
||||||
|
permute(0)
|
||||||
|
return final
|
||||||
|
|
||||||
|
def pure_polynomial_fit(blocks, dim): # RESIZE TO 2 PI !!!!!!#
|
||||||
|
'''
|
||||||
|
A polynomial of P(n-1) is generated with an n dimensional block,
|
||||||
|
by calculating the a system of n equations, solved through LU
|
||||||
|
decomposition.
|
||||||
|
'''
|
||||||
|
def permute(c, n, dim=[]):
|
||||||
|
if n == len(c):
|
||||||
|
d = tuple(dim)
|
||||||
|
b = blocks[d].flatten()[::-1]
|
||||||
|
pb = p_inv.dot(b)
|
||||||
|
y = spla.solve_triangular(l, pb, lower=True, check_finite=False)
|
||||||
|
x = spla.solve_triangular(u, y, check_finite=False)
|
||||||
|
block_polynomials[d] = x
|
||||||
|
if np.sum(dim[1:]) == 0:
|
||||||
|
system('cls')
|
||||||
|
print("Fit Poly Block {:.2f}%".format(100*dim[0]/c[0]))
|
||||||
|
else:
|
||||||
|
for x in range(c[n]):
|
||||||
|
permute(c, n+1, dim+[x])
|
||||||
|
|
||||||
|
degree = blocks.shape[-1] - 1
|
||||||
|
deg_perm = permutations(dim*[list(reversed(range(degree+1)))])
|
||||||
|
# Scale the coordinate system from 0 to 2pi, for preparation of DFT.
|
||||||
|
block_coord_perm = (2*math.pi/(degree+1)) * deg_perm[:]
|
||||||
|
|
||||||
|
mat_size = int(math.pow(degree + 1, dim))
|
||||||
|
a = np.zeros((mat_size, mat_size), dtype=np.uint64)
|
||||||
|
for i,perm in enumerate(block_coord_perm):
|
||||||
|
a[i] = np.prod(np.power(perm, deg_perm), axis=1, dtype=np.uint64)
|
||||||
|
|
||||||
|
p, l, u = spla.lu(a)
|
||||||
|
p_inv = np.linalg.inv(p)
|
||||||
|
poly_shape = list(blocks.shape[:-dim]) + [mat_size]
|
||||||
|
block_polynomials = np.zeros(tuple(poly_shape), dtype=np.float64)
|
||||||
|
permute(blocks.shape[:-dim], 0)
|
||||||
|
|
||||||
|
return block_polynomials
|
||||||
|
|
||||||
|
|
||||||
|
def trig_taylor_fit(block):
|
||||||
|
'''
|
||||||
|
Assume the polynomial will be a n-dimensional taylor polynomial,
|
||||||
|
calculate a polynomial regression that will represent the inputs.
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
def nd_dft(poly, dim):
|
||||||
|
'''
|
||||||
|
This function calculates a N-dimensional Discrete Fourier Transform,
|
||||||
|
specifically where f(t) is a polynomial.
|
||||||
|
'''
|
||||||
|
def get_integral_mat(n, x, zero, imag):
|
||||||
|
'''
|
||||||
|
Matrix represents T: P -> K, where P,K have basis' respectively:
|
||||||
|
P: x^n, x^(n-1), x^(n-2), ..., c, ix^n, ix^(n-1), ix^(n-2), ..., ic
|
||||||
|
K: c, 1/k, 1/k^2, ..., 1/k^n, ic, i/k, i/k^2, ..., i/k^n
|
||||||
|
|
||||||
|
This function returns a matrix to calculate the one-dimensional
|
||||||
|
integral. If the argument zero is true, the function will return
|
||||||
|
a matrix assuming the definite integral is from 0.
|
||||||
|
'''
|
||||||
|
mat_rr, mat_ri, mat_ir, mat_ii = [], [], [], []
|
||||||
|
|
||||||
|
def get_mat_part(zero_row_cond, neg_cond):
|
||||||
|
mat_part = []
|
||||||
|
for row in range(n+1):
|
||||||
|
if row % 2 == zero_row_cond:
|
||||||
|
mat_part.append([0]*(n+1))
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
row_vec = []
|
||||||
|
|
||||||
|
for col in range(n+1):
|
||||||
|
x_pow = n-col-row
|
||||||
|
if x_pow < 0:
|
||||||
|
row_vec.append(0)
|
||||||
|
elif x_pow == 0 and zero:
|
||||||
|
row_vec.append(0)
|
||||||
|
else:
|
||||||
|
neg = -1 if (row - neg_cond) % 4 == 0 else 1
|
||||||
|
const = math.factorial(n-col)/math.factorial(n-col-row)
|
||||||
|
row_vec.append(neg*const*math.pow(x, n-col-row))
|
||||||
|
mat_part.append(row_vec)
|
||||||
|
return np.array(mat_part, dtype=np.float64)
|
||||||
|
|
||||||
|
mat_r = np.concatenate([get_mat_part(0, 3), get_mat_part(1, 2)])
|
||||||
|
if imag:
|
||||||
|
mat_i = np.concatenate([get_mat_part(1, 0), get_mat_part(0, 3)])
|
||||||
|
return np.concatenate([mat_r, mat_i], axis=1)
|
||||||
|
else:
|
||||||
|
return mat_r
|
||||||
|
|
||||||
|
def get_mono_mats(block):
|
||||||
|
rind, iind = np.nonzero(rblock), np.nonzero(iblock)
|
||||||
|
rmono_a, imono_a = rblock[rind], iblock[iind]
|
||||||
|
rmono_deg = np.subtract(deg, np.array(deg_perm)[rind].transpose())
|
||||||
|
imono_deg = np.subtract(2*deg+1, np.array(deg_perm)[iind].transpose())
|
||||||
|
|
||||||
|
mono_count = len(rmono_a) + len(imono_a)
|
||||||
|
mono_mats = np.zeros((dim, mono_count, 2*deg+2))
|
||||||
|
for x in range(dim):
|
||||||
|
mono_deg = np.concatenate([rmono_deg, imono_deg], axis=1)
|
||||||
|
mono_mat[x][np.arange(mono_count), mono_deg[x]]
|
||||||
|
|
||||||
|
return mono_mats
|
||||||
|
|
||||||
|
def precompute_integrals(k_max, dim, degree):
|
||||||
|
'''
|
||||||
|
This function returns all possible combinations of monomial
|
||||||
|
integrals precomputed for all 'k' until k_max excluding k = 0.
|
||||||
|
'''
|
||||||
|
integral_k = np.zeros((degree, k_max-1), dtype=np.float64)
|
||||||
|
mat = get_integral_mat(degree, 2*math.pi, True, False)
|
||||||
|
k_col = np.arange(1, k_max).reshape((k_max-1, 1))
|
||||||
|
k_pow = np.power(k_col, -np.arange(1, degree+2).astype('float64'))
|
||||||
|
k_b = np.concatenate([k_pow, 1j*k_pow], axis=1).transpose()
|
||||||
|
|
||||||
|
mono_integrals = mat.transpose().dot(k_b)
|
||||||
|
# Offset by degree for deg_perm to fit basis x^n, x^(n-1) ... 1.
|
||||||
|
deg_perm = permutations(dim*[list(range(degree+1))])
|
||||||
|
k_perm = magnitude_spiral(dim*[list(range(1, k_max))])
|
||||||
|
poly_integrals = []
|
||||||
|
for deg in deg_perm:
|
||||||
|
k_perm_prod = []
|
||||||
|
for k_vec in k_perm:
|
||||||
|
k_perm_prod.append(np.prod(mono_integrals[deg, k_vec]))
|
||||||
|
poly_integrals.append(k_perm_prod)
|
||||||
|
|
||||||
|
return np.array(poly_integrals)
|
||||||
|
|
||||||
|
def magnitude_spiral(dim, k_max):
|
||||||
|
|
||||||
|
k_perm = permutations(dim*[list(range(-k_max, k_max+1))])
|
||||||
|
k_vecs = {}
|
||||||
|
for k_vec in k_perm:
|
||||||
|
mag = np.linalg.norm(k_vec)
|
||||||
|
try:
|
||||||
|
k_vecs[mag].append(k_vec)
|
||||||
|
except KeyError:
|
||||||
|
k_vecs[mag] = [k_vec]
|
||||||
|
k_vec_sort = {}
|
||||||
|
for mag in list(sorted(k_vecs.keys())):
|
||||||
|
k_vec_sort[mag] = sorted(k_vecs[mag], key=lambda x: list(np.abs(x)))
|
||||||
|
|
||||||
|
return np.concatenate(list(k_vec_sort.values()))
|
||||||
|
|
||||||
|
deg = int(math.sqrt(poly.shape[-1], 1/dim)) - 1
|
||||||
|
|
||||||
|
# In form [Degree Permutation, K permutation]
|
||||||
|
poly_integrals = precompute_integrals(int(math.pow(1000, 1/deg)), dim, deg)
|
||||||
|
|
||||||
|
|
||||||
|
###### FINISH LOOP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
C_DIM = 4
|
||||||
|
|
||||||
|
video = np.array(read_video(50))
|
||||||
|
vid_blocks = change_dimension(video, C_DIM)
|
||||||
|
block_poly = np.round(pure_polynomial_fit(vid_blocks, C_DIM), 5)
|
||||||
|
|
||||||
|
print(video_blocks[0])
|
||||||
|
c_k = []
|
||||||
|
#for poly in block_polynomials:
|
||||||
|
|
||||||
|
|
||||||
|
#img = Image.fromarray(video[1000])
|
||||||
|
#img.save('D:/Videos/test.png')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
x
Reference in New Issue
Block a user