Webcam pulsometer (032; 11.10.2012; image processing)

 

 

       Artykuł przedstawiający koncepcję pomiaru tętna z użyciem kamery internetowej. Na początek wideo prezentujące działanie aplikacji:

 

Webcam pulsometer from MyInventions on Vimeo.

 

 

 

Zasada działania

 

Koncepcja pomiaru tętna oparta została na zasadzie działania pulsoksymetru medycznego. Za pomocą programu napisanego w środowisku Processing analizujemy obraz światła przechodzącego przez palec przyłożony do obiektywu. Dodatkową inspiracją do projektu była praca Eulerian Video Magnification (polecam wideo).

 

 

Pierwsze podejście

 

Rozpocznijmy od najprostszego kodu w Processingu, który wyświetli obraz z kamery w oknie. Tu ograniczymy się do obejrzenia tylko niebieskiej składowej obrazu (w testach niebieski kolor okazał się lepszy od czerwonego). Bardzo istotne będzie tu odpowiednie skonfigurowanie kamery internetowej - ustalenie stałej ekspozycji i balansu bieli. Do obsługi wideo w środowisku Processing użyłem biblioteki GSVideo zamiast standardowej Video (GSVideo nie wymaga instalacji QuickTime'a lub WinVDIG).


Creative live cam Optia configuration
import codeanticode.gsvideo.*;
GSCapture webcam;
int pixNumber;
color Kolor;
int A, R, G, B;

void setup() {
	size(640, 480);
	webcam = new GSCapture(this, 640, 480);
	webcam.start();
	pixNumber = webcam.width*webcam.height;
	stroke(255, 0, 0);
	A = 255 << 24;
}

void draw() {
	if (webcam.available() == true) {
		webcam.read();
		for (int i = 0; i < pixNumber; i++ ) {
			Kolor = webcam.pixels[i];
			B = Kolor & 0xFF;
			R = 0;
			G = 0;
			webcam.pixels[i]=A|R|G|B;
		}
		set(0, 0, webcam);
	}
}

Po przyłożeniu nieruchomo palca do obiektywu kamery (nie naciskamy) i odpowiednim ustawieniu oświetlenia zauważymy na ekranie regularne migotanie obrazu.

 

 

Drugie podejście

 

Przeprowadźmy teraz analizę obrazu aby automatycznie wydobyć z niego informację o zmianie obrazu. Zaproponuję prostą metodę zsumowania kolorów pewnej liczby pikseli równomiernie rozłożonych na obrazie. Zmiany jasności koloru będą zatem wpływać na ostateczną wartość owej sumy. Do wykrycia uderzenia serca najlepiej jest śledzić zmiany sumarycznego koloru między kolejnymi klatkami obrazu. A oto kod:


import codeanticode.gsvideo.*;
GSCapture webcam;
int pixNumber;
color Kolor;
int A, R, G, B, S, pS, D, block=0;
float interrupt = 50.0; // wartość sumy kolorów której przekroczenie
						// traktujemy jako impuls
float scal = 25.0; // skalowanie sumy kolorów pikseli
float ms, pms;
int ticks = 0;
int dT = 10;
int dTick = 15; // liczba uderzeń po których przeliczamy tętno

void setup() {
	size(160, 350);
	webcam = new GSCapture(this, 160, 120); // wystarczy najmniejszy obraz z kamery
	webcam.start();
	pixNumber = webcam.width*webcam.height;
}


void draw() {
	if (webcam.available() == true) {
		webcam.read();
		for (int i = 0; i < pixNumber; i++) {
			Kolor = webcam.pixels[i];
			A = 255 << 24;
			R = 0;
			G = 0;
			B = Kolor & 0xFF;
			webcam.pixels[i]=A|R|G|B;
		}
		background(100);
		set(0, 0, webcam); // wyświetlenie obrazu z kamery

		// sumujemy kolory 100 równomiernie rozłożonych pikseli
		S = 0;
		for (int i=0; i<liczbaPikseli; i+=pixNumber/100) {
			S += webcam.pixels[i] & 0xFF;
		}

		D = S-pS; // przyrost sumy
		pS = S;
		fill(0,0);
		stroke(0);
		rect(40, 330, 80, -200); // ramka wskaźnika
		fill(255,0,0);
		stroke(0,200,0);
		line(40,230-interrupt,120,230-interrupt); // poziom zliczany
		stroke(0);
		rect(40, 230, 80, (int)((float)D/scal)); // wartość sumy

		// detect pulses
		if ((-(float)D/scal) > interrupt && (block == 0)) {
			print("*");
			ticks++;
			block = 3; // pozwala wyeliminować podwójne zliczanie jednego impulsu
		}
		if (block > 0) {
			block--;
		}

		// ostateczne obliczenie pulsu
		if (ticks == dTick) {
			ms = millis();
			print(60.0*dTick*1000.0/(ms - pms));
			pms = ms;
			ticks = 0;
		}
	}
}

 

 

Co dalej?

 

Kolejnym etapem pracy może być oczywiście stworzenie ładnego interfejsu graficznego dla programu (tak jak zrobiłem to w filmie). Warto również spróbować uniezależnić funkcjonowanie programu od zmiennych warunków oświetlenia. Wyzwaniem może być próba wydobycia informacji o pulsie z obrazu nieruchomej osoby bez stosowania metody "prześwietlania".


© Copyright Sebastian Korczak 2009 - 2024 english versionpolish version