Use cv2.warpPerspective instead of dumb interpolation
https://docs.opencv.org/4.9.0/da/d6e/tutorial_py_geometric_transformations.html
This commit is contained in:
parent
80b6b746b8
commit
6dacec9675
3 changed files with 16 additions and 43 deletions
|
@ -10,11 +10,11 @@ pip install --upgrade reedsolo --no-binary "reedsolo" --no-cache --config-settin
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Encode: `python encoder.py -i in -o vid.mkv`
|
Encode: `python encoder.py -i in`
|
||||||
|
|
||||||
Play video: `mpv --scale=nearest --fullscreen --loop --no-keepaspect vid.mkv`
|
Play video: `mpv --scale=nearest --fullscreen --loop --no-keepaspect vid.mkv`
|
||||||
|
|
||||||
Copy the flags printed by the encoder and pass them to the decoder: `python decoder.py -o out FLAGS`
|
Copy the flags printed by the encoder and pass them to the decoder: `python decoder.py FLAGS`
|
||||||
|
|
||||||
Formatting: `black -l 120 *.py`
|
Formatting: `black -l 120 *.py`
|
||||||
|
|
||||||
|
|
51
decoder.py
51
decoder.py
|
@ -1,15 +1,14 @@
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
|
||||||
import traceback
|
import traceback
|
||||||
import cv2
|
import cv2
|
||||||
import matplotlib.pyplot as plt
|
# import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from creedsolo import RSCodec
|
from creedsolo import RSCodec
|
||||||
from raptorq import Decoder
|
from raptorq import Decoder
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||||
parser.add_argument("-i", "--input", help="camera device index or input video file", default=0)
|
parser.add_argument("-i", "--input", help="camera device index or input video file", default=0)
|
||||||
parser.add_argument("-o", "--output", help="output file for decoded data")
|
parser.add_argument("-o", "--output", help="output file for decoded data", default="out")
|
||||||
parser.add_argument("-x", "--height", help="grid height", default=100, type=int)
|
parser.add_argument("-x", "--height", help="grid height", default=100, type=int)
|
||||||
parser.add_argument("-y", "--width", help="grid width", default=100, type=int)
|
parser.add_argument("-y", "--width", help="grid width", default=100, type=int)
|
||||||
parser.add_argument("-f", "--fps", help="frame rate", default=30, type=int)
|
parser.add_argument("-f", "--fps", help="frame rate", default=30, type=int)
|
||||||
|
@ -38,7 +37,7 @@ def find_corner(A, f):
|
||||||
mask = cv2.floodFill(
|
mask = cv2.floodFill(
|
||||||
A,
|
A,
|
||||||
np.empty(0),
|
np.empty(0),
|
||||||
tuple(reversed(guess)),
|
tuple(np.flip(guess)),
|
||||||
0,
|
0,
|
||||||
(100, 100, 100),
|
(100, 100, 100),
|
||||||
(100, 100, 100),
|
(100, 100, 100),
|
||||||
|
@ -83,42 +82,16 @@ while data is None:
|
||||||
bcol -= origin
|
bcol -= origin
|
||||||
F = 255 * np.linalg.inv(np.stack((rcol, gcol, bcol)).T)
|
F = 255 * np.linalg.inv(np.stack((rcol, gcol, bcol)).T)
|
||||||
|
|
||||||
# Dumb perspective transform
|
cch = cheight / 2 - 1
|
||||||
xv = np.linspace(
|
ccw = cwidth / 2 - 1
|
||||||
-(cheight / 2 - 1) / (args.height - cheight + 1),
|
M = cv2.getPerspectiveTransform(
|
||||||
1 + (cheight / 2 - 1) / (args.height - cheight + 1),
|
np.float32([np.flip(widx), np.flip(ridx), np.flip(gidx), np.flip(bidx)]),
|
||||||
args.height,
|
np.float32([[ccw, cch], [args.width - ccw - 1, cch], [ccw, args.height - ccw - 1], [args.width - ccw - 1, args.height - cch - 1]]),
|
||||||
)
|
)
|
||||||
yv = np.linspace(
|
frame = cv2.warpPerspective(raw_frame, M, (args.width, args.height))
|
||||||
-(cwidth / 2 - 1) / (args.width - cwidth + 1),
|
|
||||||
1 + (cwidth / 2 - 1) / (args.width - cwidth + 1),
|
|
||||||
args.width,
|
|
||||||
)
|
|
||||||
xp = (
|
|
||||||
np.outer(1 - xv, 1 - yv) * widx[0]
|
|
||||||
+ np.outer(1 - xv, yv) * ridx[0]
|
|
||||||
+ np.outer(xv, 1 - yv) * gidx[0]
|
|
||||||
+ np.outer(xv, yv) * bidx[0]
|
|
||||||
)
|
|
||||||
yp = (
|
|
||||||
np.outer(1 - xv, 1 - yv) * widx[1]
|
|
||||||
+ np.outer(1 - xv, yv) * ridx[1]
|
|
||||||
+ np.outer(xv, 1 - yv) * gidx[1]
|
|
||||||
+ np.outer(xv, yv) * bidx[1]
|
|
||||||
)
|
|
||||||
|
|
||||||
# plt.scatter(widx[1], widx[0])
|
|
||||||
# plt.scatter(ridx[1], ridx[0])
|
|
||||||
# plt.scatter(gidx[1], gidx[0])
|
|
||||||
# plt.scatter(bidx[1], bidx[0])
|
|
||||||
# plt.scatter(yp, xp)
|
|
||||||
# plt.imshow(raw_frame.astype(np.uint8))
|
|
||||||
# plt.show()
|
|
||||||
|
|
||||||
frame = raw_frame[
|
|
||||||
np.clip(np.round(xp).astype(np.int64), 0, X - 1), np.clip(np.round(yp).astype(np.int64), 0, Y - 1), :
|
|
||||||
]
|
|
||||||
frame = (np.squeeze(F @ (frame - origin)[..., np.newaxis]) >= 128).astype(np.uint8)
|
frame = (np.squeeze(F @ (frame - origin)[..., np.newaxis]) >= 128).astype(np.uint8)
|
||||||
|
# plt.imshow(frame * 255)
|
||||||
|
# plt.show()
|
||||||
frame = np.concatenate(
|
frame = np.concatenate(
|
||||||
(
|
(
|
||||||
frame[:cheight, cwidth : args.width - cwidth].flatten(),
|
frame[:cheight, cwidth : args.width - cwidth].flatten(),
|
||||||
|
@ -130,7 +103,7 @@ while data is None:
|
||||||
data = decoder.decode(bytes(rsc.decode(bytearray(np.packbits(frame) ^ frame_xor))[0][: args.psize]))
|
data = decoder.decode(bytes(rsc.decode(bytearray(np.packbits(frame) ^ frame_xor))[0][: args.psize]))
|
||||||
print("Decoded frame")
|
print("Decoded frame")
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit()
|
break
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
with open(args.output, "wb") as f:
|
with open(args.output, "wb") as f:
|
||||||
|
|
|
@ -6,7 +6,7 @@ from raptorq import Encoder
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||||
parser.add_argument("-i", "--input", help="input file")
|
parser.add_argument("-i", "--input", help="input file")
|
||||||
parser.add_argument("-o", "--output", help="output video file")
|
parser.add_argument("-o", "--output", help="output video file", default="vid.mkv")
|
||||||
parser.add_argument("-x", "--height", help="grid height", default=100, type=int)
|
parser.add_argument("-x", "--height", help="grid height", default=100, type=int)
|
||||||
parser.add_argument("-y", "--width", help="grid width", default=100, type=int)
|
parser.add_argument("-y", "--width", help="grid width", default=100, type=int)
|
||||||
parser.add_argument("-f", "--fps", help="frame rate", default=30, type=int)
|
parser.add_argument("-f", "--fps", help="frame rate", default=30, type=int)
|
||||||
|
@ -39,7 +39,7 @@ rcorner = np.pad(np.dstack((ones, zeros, zeros)), ((0, 1), (1, 0), (0, 0)))
|
||||||
gcorner = np.pad(np.dstack((zeros, ones, zeros)), ((1, 0), (0, 1), (0, 0)))
|
gcorner = np.pad(np.dstack((zeros, ones, zeros)), ((1, 0), (0, 1), (0, 0)))
|
||||||
bcorner = np.pad(np.dstack((zeros, zeros, ones)), ((1, 0), (1, 0), (0, 0)))
|
bcorner = np.pad(np.dstack((zeros, zeros, ones)), ((1, 0), (1, 0), (0, 0)))
|
||||||
|
|
||||||
print(f"-x {args.height} -y {args.width} -l {args.level} -s {len(data)} -p {len(packets[0])}")
|
print(f"-x {args.height} -y {args.width} -l {args.level} -s {len(data)} -p {len(packets[0])}", end="")
|
||||||
|
|
||||||
|
|
||||||
def frame(packet):
|
def frame(packet):
|
||||||
|
|
Loading…
Reference in a new issue