Browse Source

Local RSS feed added, new (TV) emblem, diverse ...

master
kln 11 months ago
parent
commit
7e982884a3
5 changed files with 81 additions and 44 deletions
  1. +42
    -0
      FakeNews.xml
  2. +8
    -4
      README.md
  3. BIN
      emblem.png
  4. +22
    -34
      funcam.py
  5. +9
    -6
      virtcam.sh

+ 42
- 0
FakeNews.xml View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">Silly news</title><subtitle type="html">Fake news distribution</subtitle>
<updated>2020-05-12T11:13:00+02:00</updated>
<id>file://FakeNews.xml</id>
<author>
<name>wlast</name><uri>https://fakenews.ru</uri>
</author>
<link rel="self" type="application/atom+xml" href="file://FakeNews.xml"/>
<link rel="alternate" type="text/html" href="file://FakeNews.xml"/>
<rights>Copyright (c) 2020 by fakenews Corp.</rights>
<entry>
<title type="text">Disclaimer: This IS fake news (says a cretan).</title>
<id>file://FakeNews.xml/3</id>
<updated>2020-05-11T13:16:00+02:00</updated>
<published>2020-05-11T13:16:00+02:00</published>
<link href="file://FakeNews.xml"/>
<summary type="html">This is message #3</summary>
</entry>
<entry>
<title type="text">National Enquirer: hacKNology may be part of deep state.</title>
<id>file://FakeNews.xml/2</id>
<updated>2020-05-12T06:55:00+02:00</updated>
<published>2020-05-12T06:55:00+02:00</published>
<link href="file://FakeNews.xml"/>
<summary type="html">This is message #2</summary>
</entry>
<entry>
<title type="text">Reptiloids warn: hacKNology seeks world domination!</title>
<id>file://FakeNews.xml/1</id>
<updated>2020-05-12T11:13:00+02:00</updated>
<published>2020-05-12T11:13:00+02:00</published>
<link href="file://FakeNews.xml"/>
<summary type="html">This is message #1</summary>
</entry>
</feed>

+ 8
- 4
README.md View File

@ -3,16 +3,20 @@
The actual description can be found at
https://www.hacknology.de/projekt/2020/pimpedwebcam/
The emblem.png can be retrieved from
https://upload.wikimedia.org/wikipedia/commons/a/af/Tux.png
(Take this one for now, I will add an original later ...)
As there has been confusion about the correct config.ini for akvcam,
I added a functioning one (store as /etc/akvcam/config.ini - w/ root rights!).
Also: You will need a 3rd gen. Intel i7/equivalent or better ...
12.05.20 New/improved features
Local RSS 'fake news' fun added
A more appropriate '3D' logo created
Background removal improved (a little bit)
More script parameters ...
Annoying 'empty room' start screen dropped
11.05.20 New/improved features


BIN
emblem.png View File

Before After
Width: 265  |  Height: 314  |  Size: 12 KiB Width: 226  |  Height: 114  |  Size: 15 KiB

+ 22
- 34
funcam.py View File

@ -11,6 +11,7 @@ History:
06.05.20/KQ Release version
09.05.20/KQ Message translation, exception handling, arg passing improved, more general emblem.png
09.05.20/KQ Background removal ('green screen'), beta & thus really ugly ...
12.05.20/KQ Round kernels shall improve green screen (a little bit), local file rss feed provided
"""
import numpy as np
@ -20,7 +21,7 @@ import datetime, time
import cv2
import feedparser # To install: Activate (cv) environment, then 'pip3 install feedparser'
print("<<< funcam started ... >>>",file=sys.stderr)
print("\n<<< funcam started ... >>>",file=sys.stderr)
# Hint: print() to stderr (fh#2) as the actual video stream goes to stdout (fh#1)!
print("OpenCV version : "+str(cv2.__version__),file=sys.stderr) # For control purposes
@ -48,8 +49,9 @@ else:
alternate_background = None
# Prepare scroll line message as an RSS feed. Currently, this is only read once upon start ...
''' # Example of an actual RSS feed
# Example of an actual RSS feed
d = feedparser.parse(rssfeed)
print("Feed entries: " + str(len(d.entries)),file=sys.stderr)
dt0 = datetime.datetime.strptime(d.entries[2].published, '%Y-%m-%dT%H:%M:%S+02:00').strftime('%H:%M')
sRSS0 = dt0 + " " + d.entries[2].title + " +++ "
dt1 = datetime.datetime.strptime(d.entries[1].published, '%Y-%m-%dT%H:%M:%S+02:00').strftime('%H:%M')
@ -58,12 +60,6 @@ dt2 = datetime.datetime.strptime(d.entries[0].published, '%Y-%m-%dT%H:%M:%S+02:0
sRSS2 = dt2 + " " + d.entries[0].title + " +++ "
msg = "+++ " + sRSS0 + sRSS1 + sRSS2
msg = msg.translate(str.maketrans({"ä":"ae", "ö":"oe", "ü":"ue", "ß":"ss", "Ä":"Ae", "Ö":"Oe", "Ü":"Ue"}))
'''
# Alternate reality ...
msg = "+++ Reptiloids warn: hacKNology seeks world domination! "\
"+++ National Enquirer: hacKNology may be part of deep state "\
"+++ Disclaimer: This IS fake news! (says a cretan) "
lenmsg = len(msg)
scroll_x = 500 # Scroll text background offset
@ -76,8 +72,8 @@ scr_width = 40 # Initial (full) width
scr_sign = -1 # Start shrinking
alpha = 0.5 # 0.5 (0..1)
beta = (1.0 - alpha)
x_offset = 16
y_offset = 16
x_offset = 6
y_offset = 12
# Prepare background 'greenscreen'
if alternate_background != None:
@ -135,24 +131,18 @@ def do_alternate_background(current_frame,background_frame,alternate_frame):
lower_black = np.array([0, 0, 0])
upper_black = np.array([80, 80, 80])
mask = cv2.inRange(delta_frame, lower_black, upper_black) # Yields black&white
#sys.stdout.buffer.write(mask.tobytes())
# test next: hull = cv.convexHull(cnt)
# Attn.: We're operating on an inverse mask!
# dilate actually increases (white) background
# erode actually increases (black) foreground
kernel2 = np.ones((5,5),np.uint8) # Clear artefacts
# erode actually increases (black) foreground
kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) # Clear artefacts
mask = cv2.dilate(mask,kernel2,iterations=1)
#kernel = np.ones((63,63),np.uint8) # 31 ok
kernel = np.ones((9,9),np.uint8) # 31 ok
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(9,9)) # Clear artefacts
mask2 = cv2.erode(mask,kernel,iterations=7)
#sys.stdout.buffer.write(mask2.tobytes())
kernel2 = np.ones((3,3),np.uint8) # 9,23 ok
kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)) # Clear artefacts
mask3 = cv2.dilate(mask2,kernel2,iterations=1)
#sys.stdout.buffer.write(mask3.tobytes())
masked_image = np.copy(current_frame)
masked_image[mask3 != 0] = [0, 0, 0] # From foreground take modified part (us!)
@ -177,19 +167,17 @@ except:
print("*** Can't open webcam!",file=sys.stderr)
exit(-2)
print("Please take your chair & get out of the picture!\nWait 5s for continuation message ...",file=sys.stderr)
time.sleep(5) # Time for operator to disappear!
print("1. Please pick your chair & get out of the picture together!\n2. Wait 5s for continuation message ...",file=sys.stderr)
time.sleep(3) # Time for operator to disappear!
if alternate_background != None: # Shall we provide an alternative background?
for i in range(1,75): # Warmup skip ...
for i in range(1,75): # Warmup skip ... (~2s)
ret, background_frame = cap.read()
if ret!=True:
print("*** Can't create background frame!",file=sys.stderr)
exit(-3)
print("Thank you! You may enter webcam range again ...",file=sys.stderr)
cv2.imshow('Empty room', background_frame)
cv2.waitKey(0)
cv2.destroyAllWindows()
print("\x073. Thank you! You may enter webcam range again ...\n"\
"4. Start your webcam application & connect to the virtual camera\n"\
"5. Press [Ctrl][C] to abort ...",file=sys.stderr)
while(cap.isOpened()):
try:
@ -205,19 +193,19 @@ while(cap.isOpened()):
scr_width = scr_width + scr_sign
if scr_width <= 4:
scr_sign = 1 # Start increasing
if scr_width >= 60:
if scr_width >= 100:
scr_sign = -1 # & shrinking again
src2 = cv2.resize(src1, (scr_width,76)) # w/h
src2 = cv2.resize(src1, (scr_width,60)) # w/h
overlay_image_alpha(frame,
src2[:, :, 0:3],
(x_offset+((60-scr_width)//2), y_offset),
(x_offset+((100-scr_width)//2), y_offset),
src2[:, :, 3] / 255.0)
frame4 = cv2.cvtColor(frame,cv2.COLOR_BGRA2RGB) # Correct color space
# Emblem subtext
cv2.putText(frame4, "hacKNnology TV",
(4,y_offset+76), # x,y
(4,y_offset+62), # x,y
(cv2.FONT_HERSHEY_DUPLEX), # Font
0.4, # Scaling
(255, 255, 255), # RGB
@ -302,7 +290,7 @@ while(cap.isOpened()):
(640,440), # x2,y2
(200,200,200), # Color
1) # Thickness
scroll_x = scroll_x - 4
scroll_x = scroll_x - 6
if scroll_x < -lenmsg*6*3: # was: -500 ...
scroll_x = 500
#cv2.putText(frame4, 'scroll_x:'+str(scroll_x),
@ -358,5 +346,5 @@ while(cap.isOpened()):
break
cap.release()
print("\n<<< funcam terminated. >>>",file=sys.stderr)
print("\n<<< funcam terminated. >>>\n",file=sys.stderr)

+ 9
- 6
virtcam.sh View File

@ -5,7 +5,8 @@
# History:
# --------
# 05.05.20/KQ Initial version
# 09.05.20/KQ Automatic virtual port detection (via getvirtualvideo.py)
# 09.05.20/KQ Automatic virtual port detection (via getvirtualvideo.py), several fixed values turned into parameters
# 12.05.20/KQ Local RSS feed added, more parameters ...
#
# 1. Install akvcam virtual camera devices
# 2. Activate (cv) environment script
@ -19,9 +20,10 @@
echo "Running virtcam ..."
NAMEPLATE="Expert (+++)"
# NAMEPLATE="kaqu (Klaus)"
WEBCAM=2
cd ~/cv
echo "Installing video4 (output) / video5 (capture) virtual devices ..."
echo "Installing virtual devices ..."
ls /dev/video? >videolist1.txt
cd ~/akvcam/src
sudo modprobe videodev
@ -32,15 +34,16 @@ echo "Starting 'stream modifier' application ..."
echo "Activating (cv) environment ..."
source ~/cv/bin/activate
cd ~/cv
PWD=`pwd`
ls /dev/video? >videolist2.txt
CAMPORT=`python3 getvirtualvideo.py videolist`
echo "1st virtual video port is: " $CAMPORT
echo "Actual webcam hardware assumed as: /dev/video0"
echo "Actual webcam hardware assumed as: /dev/video$WEBCAM (may require adjustment)"
echo "*** For best video conference experience (currently, 5/2020) use chromium-browser ..."
# alternate background (beta) not activated by default
# python3 funcam.py 0 $NAMEPLATE "https://www.heise.de/security/rss/news-atom.xml" alternate_background.jpg > $CAMPORT # webcam assumed as /dev/video0
python3 funcam.py 0 "$NAMEPLATE" "https://www.heise.de/security/rss/news-atom.xml" > $CAMPORT # webcam assumed as /dev/video0
python3 funcam.py $WEBCAM "$NAMEPLATE" "file://$PWD/FakeNews.xml" > $CAMPORT
#python3 funcam.py $WEBCAM "$NAMEPLATE" "file://$PWD/FakeNews.xml" alternate_background.jpg > $CAMPORT
echo "Removing virtual (camera) devices ..."
sudo rmmod akvcam.ko


Loading…
Cancel
Save