mardi 15 octobre 2024

Giving voices to your apps

I'm starting to think about developing multimodal interfaces (vision and sound) for Red. With macOS it's quite easy because we can use the ‘say’ system command. For Windows and Linux, I'd be delighted if other developers came up with a similar solution.

Here (https://github.com/ldci/Voices) are a few examples of how to use this command with Red and Rebol 3.

This is an example of Red code:

#!/usr/local/bin/red-view
Red[
Author: "ldci"
needs: view
]
;--for macOS 32-bit (Mojave) 
;--new version 
voices:         []
languages: []
sentences: []
flag:                 1
filename:   %voices.txt
getVoices: does [call/shell/output "say -v '?'" filename]
loadVoices:  does [
vfile: read/lines filename
foreach v vfile [
tmp: split v "#" 
append sentences tmp/2
trim/lines tmp/1
append voices first split tmp/1 space
append languages second split tmp/1 space
]
a/text: sentences/1
f/text: languages/1
]
generate: does [
prog: rejoin ["say -v " voices/:flag " " a/text]
call/shell/wait prog
]
mainWin: layout [
title "Voices"
dp1: drop-down data voices
select 1
on-change [
flag: face/selected
f/text: languages/(face/selected)
a/text: sentences/(face/selected)
]
f: field center
button "Talk" [generate] 
pad 100x0 
button  "Quit" [quit]
return
a: area 450x50
do [unless exists? filename [getVoices] loadVoices]
]
view mainWin


And the GUI result







lundi 14 octobre 2024

Using Unicode Characters with Red

 Unicode characters can be used with Red for making nice GUI apps. 

A sample code is here: https://github.com/ldci/Unicode/blob/main/Red/unicode5.red

But results are slightly different with macOS and Windows versions of Red.

With macOS, unicode characters are correctly displayed in a text-list (I mean with coloured characters).

This is not the case for Windows version with a black and white text-list.


This is probably related to a difference in backends for Red/View related to OS.

But, another difference is also observed when you use to-image function such as

button 200 "Copy to the clipboard" [
img: to-image cc
write-clipboard img
view [title "Image Copy" image 400x300 img button "Close" [unview]]
]

macOS gives an expected result with correct size and position.
Windows not: image is not correctly copied to the clipboard with correct size and position.



Why these differences? Not tested with Linux version of Red.

Thanks to qtxie for the fix :). Now macOS and Windows versions are similar.


Red team is very responsive !










mercredi 9 octobre 2024

Using Z-score with Red or Rebol 3

 Detecting anomalies (outliers) is a classical problem in statistics and computer science.

https://medium.com/@akashsri306/detecting-anomalies-with-z-scores-a-practical-approach-2f9a0f27458d 

Z-score can help to solve this kind of problems. Z-score is calculated as follow z = x - mean / SD  where x is an individual value in the distribution, mean is the average of all distribution values and SD is the standard deviation of the data.

When applied on Gaussian distribution of data, Z-score generates a new distribution with mean = 0.0 and SD = 1.0. This is important when you need to compare data with different scales. 

Then we can use a threshold to identify outliers. A threshold value is a  cutoff point that helps determine what is considered as an anomaly or outlier within the values distribution.  Many scientists use the Z-score to exclude values they consider to be outliers from the data: values greater than 2 SD or less than 2 SD will not be retained. 

But, we can also use Z-Score for extracting significant values from a noisy signal, with these general considerations: There is basic noise in the signal with a general mean and SD of all timeseries. There are data points that significantly deviate from the noise (peaks).

I've found a good explanation here:

https://stackoverflow.com/questions/22583391/peak-signal-detection-in-realtime-timeseries-data of how we can deal with this problem.

The basic idea is simple: if a datapoint in the series is a given x number of standard deviation away from a moving mean, the algorithm gives a signal (equal to 1 ) which means that the datapoint is emerging from the noisy signal.

This is a Red/Rebol 3 function which illustrates how to do.

zThresholding: function [
data      [block! vector!]
output    [block! vector!]
lag       [integer!]
threshold [decimal!]
influence [decimal!]
][
sLength: length? data
filteredY: copy data
;--Red 
avgFilter: make vector! reduce ['float! 64 sLength]
stdFilter: make vector! reduce ['float! 64 sLength]
;--R3
avgFilter: make vector! reduce ['decimal! 64 sLength]
stdFilter: make vector! reduce ['decimal! 64 sLength]

avgFilter/:lag: mean data lag
stdFilter/:lag: stdDev data lag
i: lag
while [i < sLenght][
n:   i + 1          ;--index of the next value
y:   data/:n
avg: avgFilter/:i
std: stdFilter/:i
v1: abs(y - avg)
v2: threshold * std
either v1 > v2 [
output/:n: pick [1 -1] y > avg
filteredY/:n: (influence * y) + ((1 - influence) * filteredY/:i)
][
output/:n: 0
]
avgFilter/:n: mean   (at filteredY i - lag) lag
stdFilter/:n: stdDev (at filteredY i - lag) lag
i: i + 1
]
filteredY
]

And the result:




See for the code for Red and Rebol: 


mardi 6 août 2024

Gems from Rebol (2)

 Other useful functions found in Rebol 3 : filter and unfiltered for png images.


Source image

Filtered image
Unfiltered image
Of course, source and unfiltered images are identical.






samedi 20 juillet 2024

Gems from Rebol

Each version of Rebol includes pearls that make image processing easy.

In Rebol 2, for example, you can find an extremely fast convolution function.  

You'll find here http://www.rebol.com/view/demos/convolve.r, the demo of convolution effect (By Cyphre).

I remember presenting Rebol at the Hanoi Polytechnic University (https://bachkhoahanoi.edu.vn/) a long time ago, and colleagues were impressed by the speed of a simple interpreted script designed for convolution.

Basically, this function uses a 3 by 3 kernel and offers various filters such as emboss and others. But you can also create your own filter.


These ideas have been implemented in redCV and you can find several examples in the RedCV/samples/image_convolution directory.

Recently, I did a little digging into the Rebol 3 version developed by Oldes (https://github.com/Siskin-framework/Rebol) and also found a few gems. 

The first is blur function which allows a Gaussian blurring of any image.
USAGE:
     BLUR image radius

DESCRIPTION:
     Blur (Gaussian) given image. 
     BLUR is a native! value.

ARGUMENTS:
     image         [image!]   Image to blur (modified).
     radius         [number!]  Blur amount.

radius must be positive and > 1. If radius = 1 you'll get an un-blurred image as result.


The second one is rgb-to-hsv function: 

USAGE:
     RGB-TO-HSV rgb

DESCRIPTION:
     Converts RGB value to HSV (hue, saturation, value). 
     RGB-TO-HSV is a native! value.

ARGUMENTS:
     rgb           [tuple!] 
     
Of course yo'll get the inverse function hsv-to-rgb:
USAGE:
     HSV-TO-RGB hsv

DESCRIPTION:
     Converts HSV (hue, saturation, value) to RGB. 
     HSV-TO-RGB is a native! value.

ARGUMENTS:
     hsv           [tuple!]   






Thanks to these fabulous developers for offering us such easy-to-use tools.






vendredi 12 juillet 2024

Red 64-bit Image

More than once while developing redCV, I regretted that Red didn't offer the possibility of creating images in 8, 16, 32 and 64 bits, with a channel number from 1 to 4 as is the case with OpenCV.  Such formats are sometimes very useful for speeding up image processing and improving precision. When we developed Matrix with Toomas Vooglaid and Qingtian Xie in 2020, we solved some of the problems. But I was left wanting more, so I did a bit of digging to find out whether Red objects could answer this question. The following code is just one illustration of such an approach.


#!/usr/local/bin/red

Red [

]


rcv: object [

create: func [

type [integer!] ;--1:byte 2:integer 3:float

bit [integer!] ;--8, 16, 32 or 64-bit

isize [pair!] ;--image size as pair!

channels [integer!] ;--1 to 4 channels

return: [vector!] ;--image data

/local

size width height [integer!]

data [vector!]

][

width: isize/x

height: isize/y

size: width * height * channels 

switch bit [

8  [data: make vector! reduce ['char! 8 (size)]]

16 [data: make vector! reduce ['integer! 16 (size)]]

32 [data: make vector! reduce ['integer! 32 (size)]]

64 [data: make vector! reduce ['float! 64 (size)]]

]

data

]

]

;********************************* tests ************************************

iSize: 256x256

random/seed now/precise

img1: rcv/create 3 64 iSize 1 ;--create a float image with 1 channel

n: length? img1

repeat i n [img1/:i: round/to random 1.0 0.01] ;--random values [0..1]

repeat i n [img1/:i: img1/:i / 1.0 * 255]         ;--random values [0..255]

bin1: copy #{} ;--binary string

repeat i n [append/dup bin1  to integer! img1/:i 3]         ;--integer values

dest1: make image! reduce [iSize bin1] ;--a grayscale Red image with 3 channels


img2: rcv/create 3 64 iSize 3 ;--create a float image with 3 channels

n: length? img2

repeat i n [img2/:i: round/to random 1.0 0.01] ;--random values [0..1]

repeat i n [img2/:i: img2/:i / 1.0 * 255]         ;--random values [0..255]

bin2: copy #{} ;--binary string

foreach [r g b] img2 [

append bin2 to-integer r ;--red channel 

append bin2 to-integer g ;--green channel

append bin2 to-integer b ;--blue channel

]

dest2: make image! reduce [iSize bin2] ;--a rgb Red image


view [

title "64-bit image test"

below

image dest1

image dest2

pad 100x0

button "Quit" [quit]