Anda di halaman 1dari 17

MENDETEKSI JUMLAH ORANG DALAM SATU

GAMBAR DENGAN BACKGROUND


SUBSTRACTION DAN LABELLING
Tugas Besar Mata Kuliah EL4127
Periode Akademik 2015 / 2016

Disusun Oleh :
Mahendra Drajat A [13212116]
Dela Natalia Malau [13212045]

EL4127 ARSITEKTUR DAN KOMPUTASI PARALEL


SEKOLAH TEKNIK ELEKTRO DAN INFORMATIKA
INSTITUT TEKNOLOGI BANDUNG
2015

1. Pendahuluan
Pendektsian jumlah orang dalam satu gambar digunakan untuk mempermudah proses
perhitungan bila diperlukan data jumlah orang dari suatu gambar dan jumlah orang
dalam gambar cukup banyak. Mendeteksi jumlah orang dalam satu gambar memiliki
urutan proses yang harus dilakukan. Ada beberapa metode yang dapat dilakukan
untuk mendeteksi jumlah orang, namun pada laporan ini digunakan metode
background substraction dan labeling image processing. Penggunaan dua metode ini
kurang menghasilkan hasil yang masksimal, dikarenakan pada hasil setelah
background substraction tidak terlalu menunjukkan suatu objek /orang, sehingga
diperlukan proses erosi dan dilasi. Berikut penjelasan setiap proses yang diperlukan
secara berurutan, yaitu
Read image dan template
Proses membaca gambar bertipe pgm dari image dan template.
Background Substraction
Proses ini memerlukan dua gambar, satu sebagai template berupa gambar
background dari image, dan kedua adalah image berupa gambar background
dengan orang. Background substraction adalah proses pengurangan image
terhadap template, hasil dari proses ini adalah hitam untuk nilai pixel yang
sama, dan putih untuk nilai pixel yang berbeda. Objek orang pada image akan
berwarna putih pada hasil background substraction.
Erosi
Erosi adalah proses morphologi (menggunakan bentuk sebagai pedoman
pengolahan) yang akan mengurangi pixel pada batas antar objek. Hasil operasi
ini adalah mengambil nilai terendah dari himpunan pixel tetangganya atau
persatu kernel (3x3 pixel). Jika ada pixel yang bernilai nol, maka output pixel
akan bernilai nol.
Dilasi
Dilasi adalah proses morphologi (menggunakan bentuk sebagai pedoman
pengolahan) yang akan menambahkan pixel pada batas anatar objek. Hasil
operasi ini adalah mengambil nilai maksimal yang diperoleh dari himpunan
pixel tetangga. Jika terdapat nilai pixel 255, maka output pixel adalah 255.
Labelling_step 1
Labeling adalah proses scanning an image, per pixel (dari atau kebawah dan
kiri ke kanan ) untuk mengedintifikasi hubungan dari sebuah area pixel.
Labelling_step 1 akan memberi nilai 1,2,3. dst berdasarkan nilai pixel
sebelumnya, sampai gambar objek dari hasil background substraction, erosi
dan dilasi tercover seleuruhnya.
Labeling_step 2
Labelling_step 2 adalah tahap membanding nilai pixel labeling_step 1,
sehingga nilai pixel pada objek orang adalah nilai terendah, yaitu 1.
Count
Proses menghitung jumlah objek orang pada gambar.

Berikut diagram alir dari cara kerja program mendeteksi jumlah orang dalam satu
gambar.

2. Kode dan Hasil


Kode
Di Lampiran.
Program ini di parallel kan dengan menggunakan MPI dan OpenMP.
Hasil
Berikut ditampilkan hasil dari program berdasarkan urutan proses yang digunakan,
Image

Template

Pada image diberikan satu objek orang dengan gambar background yang sama.
Hasil Background Substraction

Hasil Background substraction masih belum sempurna, masih terdapat garis-garis


putih dari hasil ketidaksamaan antara gambar background pada template dengan
background pada image. Ketidak samaan itu dapat dikarenakan intensitas cahaya, atau
sudut yang berbeda.
Hasil Erosi 1

Hasil Erosi 2

Hasil erosi 1 menunjukkan pengurangan garis-garis putih yang cukup signifikan,


namun masih terdapat titik-titik putih, sehingga diperlukan erosi kedua. Hasil erosi 2
menunjukkan hasil yang baik karena pada keseluruhan background berwarna hitam.
Namun gambar objek orang sediki demi sedikit juga terikut menghitam dan kurang
terlihat sebagai suatu objek.

Hasil Dilasi 1

Hasil Dilasi 2

Hasil Dilasi 3

Hasil Dilasi 4

Proses dilasi dilakukan 4 kali proses untuk memperoleh suatu bentuk objek orang
yang lebih jelas. Terlihat dari proses dilasi diberikan hasil yang signifikan dan pada
hasil dilasi 4 cukup menunjukkan suatu objek orang yang dapat diperoses selanjutnya.
Hasil Labelling_step 1

Hasil labeling_step 1 yang memberi nilai pixel dari satu sampai ratusan pada objek
orang menghasilkan gradasi warna yang dapat terlihat pada gambar diatas.
Hasil Labelling_step 2

Hasil labeling_step 2 memberikan gambar dengan warna yang sama, hasil ini
diperoleh karena pada labeling_step 2 mengbandingkan nilai pixel dari hasil
labeling_step 1 dan mengambil nilai terendah dari nilai pixel yang ada pada
labeling_step 1. Pada Labelling_step 1 memiliki nilai pixel terendah adalah 1,
sehingga warna yang ditunjukkan hitam.

3. Perbedaan Serial dengan Paralel


Berikut perbedaan hasil dari proses serial dengan proses parallel
Hasil Serial

Hasil MPI + Open MP

Hasil MPI + OpenMP 2 Processor

Hasil MPI + OpenMP 4 Processor

Hasil MPI + OpenMP 4 Processor, CPU

Program saat dijalankan parallel memiliki waktu yang lebih lama dari program yang
dijalankan serial. Pada saat program parallel dijalankan satu proses menghabiskan
waktu 0.170 detik, untuk 2 proses 0.337 detik, dan untuk 4 proses diperlukan 140.15
detik, terjadi peningkatan yang ekstrim saat pergantian 2 proses menuju 4 proses. Hal

ini diakibatkan dari program yang di proses tidak terlalu kompleks, dan waktu yang
lama ini diperlukan untuk mengirim data ke sebanyak processor digunakan dan waktu
untuk menerima kembali semua data dari semua processor yang digunakan. Saat
program berjalan, CPU berjalan 100 % atau berjalan secara maksimal. Saat dilakukan
pada 2 processor, CPU yang bekerja 1.6 % dengan memory yang digunakan 2.4 MB,
sedangkan dengan 4 processor, CPU bekerja rata-rata 24 % untuk setiap processor,
dengan menggunakan memory 62,9 MB untuk processor pertaa, dan 25 MB untuk
tiga processor yang lain.

LAMPIRAN
Code
/* Mendeteksi Jumlah orang dengan Background substraction dan labelling
/* Mahendra Drajat A (13212116)
/* Dela Natalia Malau (13212045)

*/
*/
*/

/* Source Code:
/* Include all library we need
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <mpi.h>

*/
*/

/* Declare all constant


#define dest 0
#define tag 0

*/

/* Declare all function prototype


*/
void read_pict(unsigned char pict[480][640], int *r, int *c,char *name);
void compare(unsigned char pict[480][640], int myrank, int r, int c, int
local_atas, int local_bawah, unsigned char filter[480][640], unsigned char
new_pict[480][640]);
void write_pict(unsigned char pict[480][640], int r, int c, char *name);
void erosi(unsigned char pict[480][640], unsigned char res[480][640], char
*iserotion);
void dilasi(unsigned char pict[480][640], unsigned char res[480][640]);
void labeling_step1(unsigned char pict[480][640]);
void labeling_step2(unsigned char pict[480][640], char *isdone);
void copy_imag(unsigned char pict[480][640],unsigned char copy_pict[480][640]);
int count(unsigned char pict[480][640]);
clock_t begin, end, send_begin, send_end,receive_begin, receive_end;
double time_spent,send_time_spent,receive_time_spent;
/* Begin the Main Function
int main(int argc, char *argv[])
{

*/

int npes, myrank;


short i,j,k;
int imag_width =640;
int imag_height =480; // actual image size
int temp_width, temp_height; // actual image size
unsigned char imag[480][640];
unsigned char temp[480][640];
unsigned char result[480][640];
unsigned char iserosi = 1;
unsigned char isdone = 1;
unsigned char tes = 0;
char nama[100];
unsigned char tempdata1,tempdata2;
//MPI Inisiasi
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &npes);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
//Start clock
begin = clock();
//Calculate region per process
int y = 480/npes;
int local_batas_bawah
= myrank*y;
int local_batas_atas
= (myrank+1)*y;
//Ambil data, lalu broadcast ke semuanya
if(myrank==0){
send_begin = clock();
read_pict(imag, &imag_height, &imag_width,"imag.pgm");
read_pict(temp, &temp_height, &temp_width,"temp.pgm");
for(i=1;i<npes;i++){
for(j=i*y;j<(i+1)*y;j++){
for(k=0;k<640;k++){
MPI_Send(&imag[j][k], 1, MPI_UNSIGNED_CHAR, i, 0,
MPI_COMM_WORLD);
MPI_Send(&temp[j][k], 1, MPI_UNSIGNED_CHAR, i, 1,
MPI_COMM_WORLD);
}
}
}
send_end = clock();
send_time_spent = (double)(send_end-send_begin) / CLOCKS_PER_SEC;
printf("Read and Send Time Spent : %.10f\n",send_time_spent);
}else{
for(i=local_batas_bawah;i<local_batas_atas;i++){
for(j=0;j<640;j++){
MPI_Recv(&tempdata1, 1, MPI_UNSIGNED_CHAR, 0, 0,
MPI_COMM_WORLD, &status);
imag[i][j]=tempdata1;

MPI_Recv(&tempdata2, 1, MPI_UNSIGNED_CHAR, 0, 1,
MPI_COMM_WORLD, &status);
temp[i][j]=tempdata2;
}
}
}
compare(imag,myrank,imag_height,imag_width,local_batas_atas,
local_batas_bawah,temp,result);
if(myrank==0){
receive_begin = clock();
for(i=1;i<npes;i++){
for(j=i*y;j<(i+1)*y;j++){
for(k=0;k<640;k++){
MPI_Recv(&tempdata1, 1, MPI_INT, i, 0,
MPI_COMM_WORLD, &status);
result[j][k] = tempdata1;
}
}
}
receive_end = clock();
receive_time_spent = (double)(receive_end-receive_begin) /
CLOCKS_PER_SEC;
printf("Receive Time Spent : %.10f\n",receive_time_spent);
}else{
for(i=local_batas_bawah;i<local_batas_atas;i++){
for(j=0;j<640;j++){
MPI_Send(&result[i][j], 1, MPI_INT, dest, 0,
MPI_COMM_WORLD);
}
}
}
if(myrank==0){
copy_imag(result,imag);
erosi(imag,result,&iserosi);
copy_imag(result,imag);
erosi(imag,result,&iserosi);
copy_imag(result,imag);
dilasi(imag,result);
copy_imag(result,imag);
dilasi(imag,result);
copy_imag(result,imag);
dilasi(imag,result);
copy_imag(result,imag);
dilasi(imag,result);
copy_imag(result,imag);
labeling_step1(imag);

while(isdone){
labeling_step2(imag,&isdone);
}
printf("Banyak orang = %d\n",count(imag));
end = clock();
time_spent = (double)(end-begin) / CLOCKS_PER_SEC;
printf("Time Spent : %.10f\n",time_spent);
}
MPI_Finalize();
return(0);
/* End Main Function
}
/* Source Code:
void read_pict(unsigned char pict[480][640], int *r, int *c, char *name){
int i, j, max;
FILE *in;
char line[200];
//
in=fopen("imag.pgm", "r");
// f16 image
printf("%s\n",name);
in=fopen(name, "r");
// f16 image
if(in == NULL)
{
printf("Error reading imag.pgm\n");
exit(1);
}
fgets(line, 199, in); // get PGM Type
line[strlen(line)-1]='\0'; // get rid of '\n'
if(strcmp(line, "P2") != 0)
{
printf("Cannot process %s PGM format, only P2 type\n", line);
exit(2);
}
fgets(line, 199, in); // get comment
fscanf(in, "%d %d", c, r); // get size width x height
fscanf(in, "%d", &max); // get maximum pixel value
for(i = 0; i < *r; i++)
for(j = 0; j < *c; j++)
fscanf(in, "%d", &pict[i][j]);
fclose(in);
return;
/* End read_pict function
}

*/
*/

*/

void compare(unsigned char pict[480][640], int myrank, int r, int c, int


local_atas, int local_bawah, unsigned char filter[480][640], unsigned char
new_pict[480][640]){

/*

int i, j, m, n;
filter the image
#pragma omp parallel for private(j)
for(i = local_bawah; i < local_atas; i++)

*/

for(j = 0; j < c; j++)


{
if(i==0 || i == r-1)
new_pict[i][j] = 0;
else
if(j==0 || i == c-1)
new_pict[i][j] = 0;
else
if(abs(pict[i][j]-filter[i][j])<64)
new_pict[i][j] = 0;
else
new_pict[i][j] = 255;
}
return;
/* End image_filter function
}

*/

void write_pict(unsigned char pict[480][640], int r, int c, char *name){


int i, j;
FILE *out;
out=fopen(name, "w");
fprintf(out, "P2\n");
fprintf(out, "# %s\n",name);
fprintf(out, "%d %d\n", c, r);
fprintf(out, "255\n");
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
fprintf(out, "%d\n", pict[i][j]);
}
fclose(out);
return;
/* End write_pict function
}

*/

void copy_imag(unsigned char pict[480][640], unsigned char copy_pict[480][640]){


int i,j;
#pragma omp parallel for private(j)
for(i=0;i<480;i++){
for(j=0;j<640;j++){
copy_pict[i][j]=pict[i][j];
}
}
return;
}
void erosi(unsigned char pict[480][640], unsigned char res[480][640], char
*iserotion){
short i,j;
char m,n;
*iserotion = 0;
/* copy edges

*/

#pragma omp parallel


#pragma omp for nowait
for(i = 0; i < 480; i++)
{
res[i][0] = 0;
res[i][639] = 0;
}
#pragma omp for nowait
for(j = 0; j < 640; j++)
{
res[0][j] = 0;
res[479][j] = 0;
}
#pragma omp for private(j)
for(i=1;i<479;i++){
for(j=1;j<639;j++){
if(pict[i-1][j]==255 && pict[i][j-1]==255 && pict[i][j]==255
&& pict[i][j+1]==255 && pict[i+1][j]==255){
*iserotion = 1;
res[i][j]=255;
}else{
res[i][j]=0;
}
}
}
return;
}
void labeling_step1(unsigned char pict[480][640]){
short i,j;
char m,n;
char area= 0;
#pragma omp parallel for private(j)
for(i=1;i<479;i++){
for(j=1;j<639;j++){
if(pict[i][j]!=0){
if(pict[i][j-1]!=0 && pict[i][j-1]!=255)
pict[i][j] = pict[i][j-1];
else
if(pict[i-1][j-1]!=0 && pict[i-1][j-1]!=255)
pict[i][j] = pict[i-1][j-1];
else
if(pict[i-1][j]!=0 && pict[i-1][j]!=255)
pict[i][j] = pict[i-1][j];
else
if(pict[i-1][j+1]!=0 && pict[i-1][j+1]!=255)
pict[i][j] = pict[i-1][j+1];
else
if(pict[i][j+1]!=0 && pict[i][j+1]!=255)
pict[i][j] = pict[i][j+1];
else{
area++;
pict[i][j] = area;

}
}
}
}
return;
}
void labeling_step2(unsigned char pict[480][640], char *isdone){
short i,j;
char m,n;
*isdone = 0;
#pragma omp parallel for private(j)
for(i=1;i<479;i++){
for(j=1;j<639;j++){
if(pict[i][j]!=0){
if(pict[i][j-1]!=0 && pict[i][j-1]!=255){
if(pict[i][j-1] < pict[i][j]){
*isdone = 1;
pict[i][j] = pict[i][j-1];
}
else
if(pict[i][j-1] > pict[i][j]){
*isdone = 1;
pict[i][j-1] = pict[i][j];
}
}
if(pict[i+1][j-1]!=0 && pict[i+1][j-1]!=255){
if(pict[i+1][j-1] < pict[i][j]){
*isdone = 1;
pict[i][j] = pict[i+1][j-1];
}
else
if(pict[i+1][j-1] > pict[i][j]){
*isdone = 1;
pict[i+1][j-1] = pict[i][j];
}
}
if(pict[i+1][j]!=0 && pict[i+1][j]!=255){
if(pict[i+1][j] < pict[i][j]){
*isdone = 1;
pict[i][j] = pict[i+1][j];
}
else
if(pict[i+1][j] > pict[i][j]){
*isdone = 1;
pict[i+1][j] = pict[i][j];
}
}
if(pict[i+1][j+1]!=0 && pict[i+1][j+1]!=255){
if(pict[i+1][j+1] < pict[i][j]){

*isdone = 1;
pict[i][j] = pict[i+1][j+1];
}
else
if(pict[i+1][j+1] > pict[i][j]){
*isdone = 1;
pict[i+1][j+1] = pict[i][j];
}
}
if(pict[i][j+1]!=0 && pict[i][j+1]!=255){
if(pict[i][j+1] < pict[i][j]){
*isdone = 1;
pict[i][j] = pict[i][j+1];
}
else
if(pict[i][j+1] > pict[i][j]){
*isdone = 1;
pict[i][j+1] = pict[i][j];
}
}
if(pict[i-1][j+1]!=0 && pict[i-1][j+1]!=255){
if(pict[i-1][j+1] < pict[i][j]){
*isdone = 1;
pict[i][j] = pict[i-1][j+1];
}
else
if(pict[i-1][j+1] > pict[i][j]){
*isdone = 1;
pict[i-1][j+1] = pict[i][j];
}
}
}
}
}
return;
}
void dilasi(unsigned char pict[480][640], unsigned char res[480][640]){
short i,j;
/* copy edges
#pragma omp parallel
#pragma omp for nowait
for(i = 0; i < 480; i++)
{
res[i][0] = 0;
res[i][639] = 0;
}
#pragma omp for nowait
for(j = 0; j < 640; j++)
{

*/

res[0][j] = 0;
res[479][j] = 0;
}
#pragma omp for private(j)
for(i=1;i<479;i++){
for(j=1;j<639;j++){
if(pict[i-1][j-1]==255 || pict[i-1][j]==255 || pict[i-1]
[j+1]==255 || pict[i][j-1]==255 || pict[i][j]==255 || pict[i][j+1]==255 ||
pict[i+1][j-1]==255 || pict[i+1][j]==255 || pict[i+1][j+1]==255){
res[i][j]=255;
}else{
res[i][j]=0;
}
}
}
return;
}
int count(unsigned char pict[480][640]){
int i,j,k, hasil=0;
char data[100];
char is_ada;
for(i=0;i<480;i++){
for(j=0;j<640;j++){
if(pict[i][j]!=0 && pict[i][j]!=255){
if(hasil==0){
data[hasil] = pict[i][j];
hasil++;
}else
{
is_ada = 0;
for(k=0;k<hasil;k++){
if(data[k] == pict[i][j]){
is_ada = 1;
}
}
if(is_ada == 0){
data[hasil] = pict[i][j];
hasil++;
}
}
}
}
}
return hasil;
}

Anda mungkin juga menyukai