Wednesday, February 29, 2012

Camera Simulation on 3D Data

I used third party ply_read() Matlab function to read the 3D data. I simulate the camera by changing the camera position and rotation in predefined trajectories.

Matlab Code

% USE THIRD PARTY FUNCTION TO READ 3D DATA
[Tri, Pts] = ply_read('bunny.ply', 'tri');
[elements, var] = ply_read('bunny.ply');
conf = elements.vertex.confidence;

c = size(Pts, 2); % NO OF VERTICES
f = 0.05; % F = 50mm
cam_pos = [0; 0; -0.5];
theta_x = 0; theta_y = 0; theta_z = 0;  % CAMERA ROTATION PARAMETERS
video_im = uint8(zeros(301, 301, 1, 301)); % OUTPUT IMAGE FRAMES

% MOVE CAMERA TOWARDS OBJECT IN SINE TRAJECTORY
dist1=-0.5 + sin(linspace(0,pi,100))/10; 
dist4=-0.5 - sin(linspace(0,pi,200));
% ROTATE 360 DEGREES WITH RESPECT TO Y AXIS
dist2=linspace(0,2*pi,200);
% ROTATE 360 DEGREES WITH RESPECT TO X AXIS
dist3=linspace(0,2*pi,200);
% CONCATINATED LIST
dist=[dist1,dist2,dist3];

for i = 1 : length(dist)
% CHANGE TRANSFORMATION PARAMETERS
    if(i <= length(dist1))
        cam_pos=[0;0;dist(i)];
    elseif(i <= length(dist2) + length(dist1))
        theta_y = dist(i);
    else
        theta_x = dist(i);
        theta_y = dist(i);
        theta_z = dist(i);
        cam_pos=[0;0;dist4(i-300)];
    end
% CAMERA TRANSOFRMATION MATRIX (ROTATION)
    Rx = [1 0 0; 0 cos(theta_x) -1*sin(theta_x); 0 sin(theta_x) cos(theta_x)];
    Ry = [cos(theta_y) 0 sin(theta_y); 0 1 0; -1*sin(theta_y) 0 cos(theta_y)];
    Rz = [cos(theta_z) -1*sin(theta_z) 0; sin(theta_z) cos(theta_z) 0; 0 0 1];

    eff_obj_data = Pts - repmat(cam_pos, 1, c);
    D = Rx * Ry * Rz * (eff_obj_data);
    
% APPLY TRANSFORMATION
    P = [f*eye(3) zeros(3,1)]; % CAMERA MATRIX
    im = P*[D; f*ones(1, c)];
    scaled_im = im(1 : 2, :);
    % SCALING THE IMAGE TO THE RANGE
    scaled_im(1, :) = (im(1, :)  - min(im(1, :)))./abs(im(3, :)).*600;
    scaled_im(2, :) = (im(2, :)  - min(im(2, :)))./abs(im(3, :)).*600;
    scaled_im = ceil(scaled_im) + 1;

% INTENSITY MAPPING
    im_out = zeros(301, 301);
    for j = 1 : c
        if(scaled_im(2, j) < 302 && scaled_im(1, j) < 301)
            im_out(302 - scaled_im(2, j), scaled_im(1, j)) = conf(j);
        end
    end
% COLLECTING FRAMES
video_im(:, :, :, i) = uint8(im_out.*200);
end

mov = immovie(video_im, gray);
movie2avi(mov, 'out.avi'); % SAVE VIDEO
implay(mov);

Output


4 Bit Carry Look Ahead Adder in Verilog


DataFlow Model : 4 Bit CLA

module CLA_4bit(
    output [3:0] S,
    output Cout,PG,GG,
    input [3:0] A,B,
    input Cin
    );
    wire [3:0] G,P,C;

    assign G = A & B; //Generate
    assign P = A ^ B; //Propagate
    assign C[0] = Cin;
    assign C[1] = G[0] | (P[0] & C[0]);
    assign C[2] = G[1] | (P[1] & G[0]) | (P[1] & P[0] & C[0]);
    assign C[3] = G[2] | (P[2] & G[1]) | (P[2] & P[1] & G[0]) |             (P[2] & P[1] & P[0] & C[0]);
    assign Cout = G[3] | (P[3] & G[2]) | (P[3] & P[2] & G[1]) | (P[3] & P[2] & P[1] & G[0]) |(P[3] & P[2] & P[1] & P[0] & C[0]);
    assign S = P ^ C;
    
    assign PG = P[3] & P[2] & P[1] & P[0];
    assign GG = G[3] | (P[3] & G[2]) | (P[3] & P[2] & G[1]) | (P[3] & P[2] & P[1] & G[0]);
endmodule

Test Bench : 4 Bit CLA

module Test_CLA_4bit;
    // Inputs
    reg [3:0] A;
    reg [3:0] B;
    reg Cin;

    // Outputs
    wire [3:0] S;
    wire Cout;
    wire PG;
    wire GG;

    // Instantiate the Unit Under Test (UUT)
    CLA_4bit uut (
    .S(S), 
    .Cout(Cout), 
    .PG(PG), 
    .GG(GG), 
    .A(A), 
    .B(B), 
    .Cin(Cin)
    );

    initial begin
    // Initialize Inputs
    A = 0; B = 0; Cin = 0;
    // Wait 100 ns for global reset to finish
    #100;
        
    // Add stimulus here
    A=4'b0001;B=4'b0000;Cin=1'b0;
    #10 A=4'b100;B=4'b0011;Cin=1'b0;
    #10 A=4'b1101;B=4'b1010;Cin=1'b1;
    #10 A=4'b1110;B=4'b1001;Cin=1'b0;
    #10 A=4'b1111;B=4'b1010;Cin=1'b0;
    end

    initial begin
$monitor("time=",$time,, "A=%b B=%b Cin=%b : Sum=%b Cout=%b PG=%b GG=%b",A,B,Cin,S,Cout,PG,GG);
    end      
endmodule

Simulation Results

time = 0 A=0000 B=0000 Cin=0 : Sum=0000 Cout=0 PG=0 GG=0
time = 100 A=0001 B=0000 Cin=0 : Sum=0001 Cout=0 PG=0 GG=0
time = 110 A=0100 B=0011 Cin=0 : Sum=0111 Cout=0 PG=0 GG=0
time = 120 A=1101 B=1010 Cin=1 : Sum=1000 Cout=1 PG=0 GG=1
time = 130 A=1110 B=1001 Cin=0 : Sum=0111 Cout=1 PG=0 GG=1
time = 140 A=1111 B=1010 Cin=0 : Sum=1001 Cout=1 PG=0 GG=1

Thursday, February 16, 2012

4 Bit Ripple Carry Adder in Verilog


Structural Model : Half Adder

module half_adder(
    output S,C,
input A,B
    );
xor(S,A,B);
and(C,A,B);

endmodule

Structural Model : Full Adder

module full_adder(
    output S,Cout,
    input A,B,Cin
    );
wire s1,c1,c2;
half_adder HA1(s1,c1,A,B);
half_adder HA2(S,c2,s1,Cin);
or OG1(Cout,c1,c2);

endmodule

Structural Model : 4 Bit Ripple Carry Adder

module ripple_adder_4bit(
    output [3:0] Sum,
    output Cout,
    input [3:0] A,B,
    input Cin
    );
wire c1,c2,c3;
full_adder FA1(Sum[0],c1,A[0],B[0],Cin),
FA2(Sum[1],c2,A[1],B[1],c1),
FA3(Sum[2],c3,A[2],B[2],c2),
FA4(Sum[3],Cout,A[3],B[3],c3);

endmodule

Test Bench : 4 Bit Ripple Carry Adder

module test_ripple_adder_4bit;
// Inputs
reg [3:0] A;
reg [3:0] B;
reg Cin;
// Outputs
wire [3:0] Sum;
wire Cout;
// Instantiate the Unit Under Test (UUT)
ripple_adder_4bit uut (
.Sum(Sum), 
.Cout(Cout), 
.A(A), 
.B(B), 
.Cin(Cin)
);
initial begin
// Initialize Inputs
A = 0;
B = 0;
Cin = 0;
// Wait 100 ns for global reset to finish
#100;        
// Add stimulus here
A=4'b0001;B=4'b0000;Cin=1'b0;
#10 A=4'b1010;B=4'b0011;Cin=1'b0;
#10 A=4'b1101;B=4'b1010;Cin=1'b1;
end
initial begin
$monitor("time=",$time,, "A=%b B=%b Cin=%b : Sum=%b Cout=%b",A,B,Cin,Sum,Cout);
end
      
endmodule

Saturday, February 11, 2012

Graph Cut Segmentation

Here, I've used the Planar Graph Cut library on Prof. Olga Veksler's website to develop this program to segment an image using graph cuts.

OpenCV Code

#include "stdafx.h"
#include "windows.h"
#include "CutSegment.h" //include PlanarCut
#include <iostream>
#include <stdio.h>
#include <string>
#include <fstream>
#include <sstream>
#include <stdlib.h>

using namespace std;

unsigned char *loadSimplePPM(int &w, int &h, const string &filename) {
  char line[1000];
  int depth = 0;
  unsigned char *rgb = 0;
  long lastpos;
  FILE *fh = fopen(filename.c_str(), "rb");  
  w = 0, h = 0;
  fgets(line, 1000, fh);
  if (strcmp(line, "P6\n")) {
    cerr << filename << " ist keine PPM-Datei\n";
    return false;
  }
  while (!feof(fh)) {
    lastpos = ftell(fh);    
    fgets(line, 1000, fh);
    if (line[0] == '#') {
    } else if (!w) {
      if (sscanf(line, "%d %d", &w, &h) < 2) {
cerr << "Fehler beim Auslesen der Datei " << filename;
cerr << " Breite und Hoehe des Bildes erwartet\n";
return 0;
      }
    } else if (!depth) {
      if (sscanf(line, "%d", &depth) < 1) {
cerr << "Fehler beim Auslesen der Datei " << filename;
cerr << " Farbtiefe erwartet\n";
return 0;
      }
    } else {
      rgb = new unsigned char[w*h*3];
      fseek(fh, lastpos, SEEK_SET);
      fread(rgb, 1, w*h*3, fh);
      break;
    }  
  }
  fclose(fh);
  return rgb;
}

bool saveSimplePPM(unsigned char *rgb, int w, int h, const string &filename) {
  ofstream fos(filename.c_str(), ios_base::binary);
  ostringstream ost;
  string s;
  if (!fos)
    return false;
  fos << "P6" << endl;
  ost << w << " " << h << endl;
  fos << ost.str();
  fos << "255" << endl;
  fos.write((const char*)rgb, w*h*3);
  fos.close();  
  return true;
}

unsigned char *RGBDataToGrey(unsigned char *rgb, int w, int h) {  
  unsigned char *pic = new unsigned char[w*h];
  int i;
  for (i=0; i<w*h; i++)
    pic[i] = rgb[i*3];
  return pic;
}

unsigned char *GreyDataToRGB(unsigned char *pic, int w, int h) {
  unsigned char *rgb = new unsigned char[w*h*3];
  int i;
  for (i=0; i<w*h; i++)
    rgb[i*3] = rgb[i*3+1] = rgb[i*3+2] = pic[i];  
  return rgb;
}

unsigned char *SegMaskAndGreyDataToRGB(CutPlanar::ELabel *mask, unsigned char *pic, int w, int h) {
  unsigned char *rgb = new unsigned char[w*h*3];
  int i;
  for (i=0; i<w*h; i++) {
    rgb[i*3] = (mask[i]==CutPlanar::LABEL_SINK) ? (unsigned char)(pic[i*3] / 255.f * 200.f) : 255;
    rgb[i*3+1] = (unsigned char)(pic[i*3+1] / 255.f * 200.f);
    rgb[i*3+2] = (mask[i]==CutPlanar::LABEL_SINK) ? 255 : (unsigned char)(pic[i*3+2] / 255.f * 200.f);
  }  
  return rgb;
}

unsigned char *getSegmentationInfo(unsigned char *rgb, int w, int h) {
  unsigned char *seginfo = new unsigned char[w*h];
  unsigned char r, g, b;
  int i;
  for (i=0; i<w*h; i++) {
    r = rgb[i*3];
    g = rgb[i*3+1];
    b = rgb[i*3+2];
    if (r >= 240 && g <= 10  && b <= 10) {
      seginfo[i] = 1;
    } else if (r <= 10 && g <= 10 && b >= 240) {
      seginfo[i] = 2;
    } else {
      seginfo[i] = 0;
    };
  }    
  return seginfo;
}

int _tmain(int argc, _TCHAR* argv[]) {
  CutSegment *sc;
  int w, h;
  uchar *seg, *rgb, *rgbNew, *grey;
  CutPlanar::ELabel *mask;
  size_t pos;
  string picname, segname, basename, suffix;
  char tmp[4096]; //just needed for windows character conversion  
  picname = "F:/PlanarCut/examples/pics/walk1.ppm";
  pos = picname.rfind(".ppm");
  if (pos == string::npos) {
    cerr << "testCutGrid only accepts .ppm images\n";
    return -1;
  }
  suffix = picname.substr(pos);
  basename = picname.substr(0, pos); 
  picname = basename + suffix;
  segname = basename + "seg" + suffix; 
  //load the prelabeled image from file
  rgb = loadSimplePPM(w, h, segname);
  seg = getSegmentationInfo(rgb, w, h);
  delete [] rgb;
  //load the image to be segmented from file
  rgb = loadSimplePPM(w, h, picname);
  grey = RGBDataToGrey(rgb, w, h);
  cout << "Image width: " << w << " and image height " << h << endl;
  //perform segmentation task
  sc = new CutSegment(w, h);
  sc->setImageData(grey);
  sc->setSourceSink(seg,1,2);
  cout << "Cut: " << sc->segment() << "\n";
  mask = new CutPlanar::ELabel[w*h];
  sc->getLabels(mask);
  delete sc;
  //read out segmentation result and save to disk
  rgbNew = SegMaskAndGreyDataToRGB(mask, rgb, w, h);
  saveSimplePPM(rgbNew, w, h, string("segresult.ppm"));
  //release memory
  delete [] grey;
  delete [] rgb;
  delete [] rgbNew;
  delete [] seg;
  delete [] mask;
  return 0;
}

Input

Image to be Segmented
Pre-labeled Image

Output

Segmentation Result