.vimrc

set nocompatible

syntax enable
filetype plugin indent on

set cursorline
hi cursorline cterm=none term=none
autocmd WinEnter * setlocal cursorline
autocmd WinLeave * setlocal nocursorline
highlight CursorLine guibg=#303000 ctermbg=234

colorscheme habamax


" FINDING FILES:

" Search down into subfolders
" Provides tab-completion for all file-related tasks
set path+=**

" Display all matching files when we tab complete
set wildmenu

" NOW WE CAN:
" - Hit tab to :find by partial match
" - Use * to make it fuzzy

" THINGS TO CONSIDER:
" - :b lets you autocomplete any open buffer





" TAG JUMPING:

" Create the `tags` file (may need to install ctags first)
command! MakeTags !ctags -R .

" NOW WE CAN:
" - Use ^] to jump to tag under cursor
" - Use g^] for ambiguous tags
" - Use ^t to jump back up the tag stack

" THINGS TO CONSIDER:
" - This doesn't help if you want a visual list of tags





" AUTOCOMPLETE:

" The good stuff is documented in |ins-completion|

" HIGHLIGHTS:
" - ^x^n for JUST this file
" - ^x^f for filenames (works with our path trick!)
" - ^x^] for tags only
" - ^n for anything specified by the 'complete' option

" NOW WE CAN:
" - Use ^n and ^p to go back and forth in the suggestion list





" FILE BROWSING:

" Tweaks for browsing
let g:netrw_banner=0        " disable annoying banner
let g:netrw_browse_split=4  " open in prior window
let g:netrw_altv=1          " open splits to the right
let g:netrw_liststyle=3     " tree view
let g:netrw_list_hide=netrw_gitignore#Hide()
let g:netrw_list_hide.=',\(^\|\s\s\)\zs\.\S\+'
"let g:netrw_winsize = 25

" NOW WE CAN:
" - :edit a folder to open a file browser
" - <CR>/v/t to open in an h-split/v-split/tab
" - check |netrw-browse-maps| for more mappings



" SNIPPETS:

" Read an empty HTML template and move cursor to title
nnoremap ,html :-1read $HOME/.vim/.skeleton.html<CR>3jwf>a

" NOW WE CAN:
" - Take over the world!
"   (with much fewer keystrokes)


"augroup ProjectDrawer
"  autocmd!
"  autocmd VimEnter * :Vexplore
"augroup END

"set nocompatible
"filetype off
"set encoding=utf-8

autocmd BufNewFile,BufRead *.rs set filetype=rust



"let g:rustfmt_autosave = 1
"let g:rustfmt_emit_files = 1
"let g:rustfmt_fail_silently = 0

let g:ale_linters = {'rust': ['analyzer']}

set omnifunc=ale#completion#OmniFunc
" As-you-type autocomplete
set completeopt=menu,menuone,preview,noselect,noinsert
let g:ale_completion_enabled = 1
let g:ale_completion_autoimport = 1
let g:ale_sign_column_always = 1
let g:ale_fix_on_save = 1
let g:ale_sign_error = 'X'
let g:ale_sign_warning = '!'

inoremap <silent><expr> <Tab>
      \ pumvisible() ? "\<C-n>" : "\<TAB>"

call plug#begin('~/.vim/plugged')
Plug 'rust-lang/rust.vim'
"Plug 'neoclide/coc.nvim', {'branch': 'release'}
"Plug 'preservim/nerdtree'
Plug 'dense-analysis/ale'
call plug#end()

"nnoremap <C-]> :ALEGoToDefinition<cr>
"nnoremap <C-[> :ALEFindReferences<cr>
nnoremap <C-h> :ALEHover<cr>

nmap <silent> <Leader>f <Plug>(ale_fix)
nmap <silent> <Leader>l <Plug>(ale_lint)
nmap <silent> <Leader>w <Plug>(ale_detail)
nmap <silent> <Leader>k <Plug>(ale_previous_wrap)
nmap <silent> <Leader>j <Plug>(ale_next_wrap)
nmap <silent> <Leader>d <Plug>(ale_go_to_definition)
nmap <silent> <Leader>r <Plug>(ale_find_references)

" line numbers
set nu

" status line
set statusline=
set statusline +=%5*%{&ff}%*            "file format
set statusline +=%3*\ %{''.(&fenc!=''?&fenc:&enc).''}      "Encoding
set statusline +=%3*%y%*                "file type
set statusline +=%4*\ %<%F%*            "full path
set statusline +=%2*%m%*                "modified flag
set statusline +=%1*%=%5l%*             "current line
set statusline +=%2*/%L%*               "total lines
set statusline +=%1*%4v\ %*             "virtual column number
set statusline +=%2*0x%04B\ %*          "character under cursor
set ls=2                                " alwways show status line

"inoremap <silent><expr> <TAB>
"      \ pumvisible() ? "\<C-n>" :
"      \ <SID>check_back_space() ? "\<TAB>" :
"      \ coc#refresh()
"inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"

"function! s:check_back_space() abort
"  let col = col('.') - 1
"  return !col || getline('.')[col - 1]  =~# '\s'
"endfunction

"if has('nvim')
"  inoremap <silent><expr> <c-space> coc#refresh()
"else
"  inoremap <silent><expr> <c-@> coc#refresh()
"endif

"nmap <silent> gd <Plug>(coc-definition)
"nmap <silent> gy <Plug>(coc-type-definition)
"nmap <silent> gi <Plug>(coc-implementation)
"nmap <silent> gr <Plug>(coc-references)

"nnoremap <leader>n :NERDTreeFocus<CR>
"nnoremap <C-n> :NERDTree<CR>
"nnoremap <C-t> :NERDTreeToggle<CR>
"nnoremap <C-f> :NERDTreeFind<CR>

inoremap <c-q> <Esc>:Lex<cr>:vertical resize 30<cr>
nnoremap <c-q> <Esc>:Lex<cr>:vertical resize 30<cr>

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Colors and Theming
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
highlight LineNr           ctermfg=8    ctermbg=none    cterm=none
highlight CursorLineNr     ctermfg=7    ctermbg=8       cterm=none
highlight VertSplit        ctermfg=0    ctermbg=8       cterm=none
highlight Statement        ctermfg=2    ctermbg=none    cterm=none
"highlight Directory        ctermfg=4    ctermbg=none    cterm=none
highlight StatusLine       ctermfg=7    ctermbg=8       cterm=none
highlight StatusLineNC     ctermfg=7    ctermbg=8       cterm=none
"highlight NERDTreeClosable ctermfg=2
"highlight NERDTreeOpenable ctermfg=8
"highlight Comment          ctermfg=4    ctermbg=none    cterm=italic
"highlight Constant         ctermfg=12   ctermbg=none    cterm=none
"highlight Special          ctermfg=4    ctermbg=none    cterm=none
"highlight Identifier       ctermfg=6    ctermbg=none    cterm=none
"highlight PreProc          ctermfg=5    ctermbg=none    cterm=none
"highlight String           ctermfg=12   ctermbg=none    cterm=none
"highlight Number           ctermfg=1    ctermbg=none    cterm=none
"highlight Function         ctermfg=1    ctermbg=none    cterm=none

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Open terminal inside Vim
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
map <Leader>tt :below vert term<CR>

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Splits and Tabbed Files
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set splitbelow splitright

" Remap splits navigation to just CTRL + hjkl
"nnoremap <C-h> <C-w>h
"nnoremap <C-j> <C-w>j
"nnoremap <C-k> <C-w>k
"nnoremap <C-l> <C-w>l

" Make adjusing split sizes a bit more friendly
noremap <silent> <C-Left> :vertical resize +3<CR>
noremap <silent> <C-Right> :vertical resize -3<CR>
noremap <silent> <C-Up> :resize +3<CR>
noremap <silent> <C-Down> :resize -3<CR>

" Change 2 split windows from vert to horiz or horiz to vert
map <Leader>th <C-w>t<C-w>H
map <Leader>tk <C-w>t<C-w>K
   

Rust vs Java

I am comparing the performance of a simple web service written in Rust versus one written in Java.

Rust code

https://github.com/pinootto/actix-hello

Java code

https://github.com/pinootto/muserver-hello

Performance

Rust

Java

Rust can handle 233K requests/sec, while Java can handle 108K requests/sec.

Memory

Rust

Java

Rust uses 12.4 MB of RAM, while Java uses 797 MB of RAM.

Conclusions

Rust is 2.15 times faster than Java and it uses 1.6% of the memory used by Java.

Difference of compilation

Human Detection

Today I have tried to use the human detection algorithm (HOG) of OpenCV in python.

It works, but it is too slow using only the CPU. It used all the 8 cores of an Intel i7 computer at almost 100% each.

Here is the source code:

import cv2
import imutils

# Initializing the HOG person detector
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())

cap = cv2.VideoCapture('/home/giovanni/video/tmp/Pexels Videos 2670.mp4')

while cap.isOpened():
    # Reading the video stream
    ret, image = cap.read()
    if ret:
        # image = imutils.resize(image,
        #                        width=min(600, image.shape[1]))

        # Detecting all the regions in the Image that has pedestrians inside it
        (regions, _) = hog.detectMultiScale(image,
                                            winStride=(4, 4),
                                            padding=(4, 4),
                                            scale=1.05)

        # Drawing the regions in the Image
        for (x, y, w, h) in regions:
            cv2.rectangle(image, (x, y),
                          (x + w, y + h),
                          (0, 0, 255), 2)

        # Showing the output Image
        cv2.imshow("Image", image)
    if cv2.waitKey(25) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

Result:

CPU usage (htop):

Here is a short video of the experiment:
http://www.dimingo.com/video/human-detection-opencv-python.mp4

Masked Face Detection

By doing a mix of the following two tutorials, I have built a masked face detector, based on machine learning (neural networks):

https://www.mygreatlearning.com/blog/real-time-face-detection/

Here are a few samples of the result:

Here is a short video:

https://mega.nz/file/krB03bCR#FT4jjEDhg2oFVUA2dLr5KT4D0DZGl26k4bLqcw8I02s

http://www.dimingo.com/video/video_2022-07-31_23-42-25.mp4

The elapsed time for the model to make a prediction of one face in a frame is about 40-50 ms:

Here are the jupyter notebooks + data:

https://mega.nz/file/crJFjara#_xZuCAqsAVnYDVr24A2bJi1oQFki-11eaMXgI8d1uk8

http://www.dimingo.com/neural-networks/working-face-mask-detector.tar.gz

The next step will be to try a similar masked face detector using a FPGA and compare the prediction times.

Useful links:

https://towardsdatascience.com/create-virtual-environment-using-virtualenv-and-add-it-to-jupyter-notebook-6e1bf4e03415

https://github.com/SamYuen101234/Masked_Face_Recognition

https://github.com/prajnasb/observations

https://www.kaggle.com/code/mirzamujtaba/face-mask-detection

How to control a switch by audio

Copy the following files into a directory (e.g. /opt/audio-switch)

rx-audio-adapter.sh

#!/bin/bash

rm rx.log

while true
do
        rm in.wav
        rec in.wav silence 1 0.1 3% 1 3.0 3%
        rx=$(./dtmf2num in.wav | tail -n 1 | cut -c 18-)
        echo $rx >> rx.log
        if [ "$rx" == "1" ]; then
                echo switch ON >> rx.log
                curl http://localhost:8080/on
        elif [ "$rx" == "D" ]; then
                echo switch OFF >> rx.log
                curl http://localhost:8080/off
        else
                echo unknown command >> rx.log
        fi
        sleep 1
done

 

usb-switch-service.py

Python dependencies: pyserial, web.py

import serial
import time
import json
import web

# /status       -> return the status of the switch (on/off)
# /on           -> turn ON the switch and return the status (on/off)
# /off          -> turn OFF the switch and return the status (on/off)
urls = (
    '/(.*)', 'ActionController'
)

app = web.application(urls, globals())

ser = serial.Serial('/dev/ttyUSB0')

class ActionController:
    def GET(self, action):
        status = ""
        if action == 'status':
            print "status"
            status = ser.dsr
        elif action == 'on':
            print "on"
            ser.dtr = True
            time.sleep(0.1)
            status = ser.dsr
        elif action == 'off':
            print "off"
            ser.dtr = False
            time.sleep(0.1)
            status = ser.dsr
        else:
            print "unknown command"
            status = ser.dsr
        return json.dumps(status)
      
if __name__ == "__main__":
    app.run()

 

start-switch.sh

#!/bin/bash

pushd /opt/audio-switch

# start usb-switch-service
python usb-switch-service.py > /tmp/usb-switch-service.log &
sleep 5
curl http://localhost:8080/off

# start rx-audio-adapter
rm in.wav
nohup ./rx-audio-adapter.sh > /dev/null 2>&1 &

popd

 

dtmf2num

wget http://aluigi.altervista.org/mytoolz/dtmf2num.zip

then compile it (make).

 

DTMF tones

The DTMF tone files can be generated from here:

http://www.audiocheck.net/audiocheck_dtmf.php

The rx-audio-adapter can be tested with the following script:

loop.sh

#!/bin/bash

while true
do
        aplay audiocheck.net_dtmf_1.wav
        sleep 10
        aplay audiocheck.net_dtmf_D.wav
        sleep 10
done