加载中…
博文
标签:

kernel

linux

分类: 软件

转载自 http://blog.csdn.net/stone_kingnet/article/details/3196225

 

在头文件 中定义了 【8种可用的日志级别字符串】
KERN_EMERG    用于紧急事件消息,它们一般是系统崩溃之前提示的消息。
KERN_ALERT    用于需要立即采取动作的情况。
KERN_CRIT     临界状态,通常涉及严重的硬件或软件操作失败。
KERN_ERR      用于报告错误状态;设备驱动程序会经常使用KERN_ERR来报告来自硬件的问题。
KERN_WARNING  对可能出现问题的情况进行警告,这类情况通常不会对系统造成严重问题。
KERN_NOTICE   有必要进行提示的正常情形。许多与安全相关的状况用这个级别进行汇报。
KERN_INFO     提示性信息。很多驱动程序在启动的时候,以这个级别打印出它们找到的硬件信息。
KERN_DEBUG    用于调试信息。

dmesg是从kernel的ring buffer(环缓冲区)中读取信息的.

那什么是ring buffer呢?
    在LINUX中,所有的系统信息(包内核信息)都会传送到ring buffer中.而内核产生的信息由printk()打印出来。系统启动时所看到的信息都是由该函数打印到屏幕中。 printk()打出的信息往往以 <0>...<2>... 这的数字表明消息的重要级别。高于一定的优先级别会打印到屏幕上,否则只会保留在系统的缓冲区中(ring buffer)。
    至于dmesg具体是如何从ring buffer中读取的,大家可以看dmesg.c源代码.很短,比较容易读懂.

     是syslogd这个守护进程根据/etc/syslog.conf,将不同的服务产生的Log记录到不同的文件中.
    LINUX系统启动后,由/etc/init.d/sysklogd先后启动klogd,syslogd两个守护进程。
    其中klogd会通过syslog()系统调用或者读取proc文件系统来从系统缓冲区(ring buffer)中得到由内核printk()发出的信息.而syslogd是通过klogd来读取系统内核信息.

    1> 所有系统信息是输出到ring buffer中去的.dmesg所显示的内容也是从ring buffer中读取的.
    2> LINUX系统中/etc/init.d/sysklogd会启动2个守护进程:Klogd, Syslogd
    3> klogd是负责读取内核信息的,有2种方式:
       syslog()系统调用(这个函数用法比较全,大家去MAN一下看看)直接的对/proc/kmsg进行读取(再这提一下,/proc/kmsg是专门输出内核信息的地方)
    4> Klogd的输出结果会传送给syslogd进行处理,syslogd会根据/etc/syslog.conf的配置把log信息输出到/var/log/下的不同文件中.

注意将printk与syslog接合使用, 用在内核开发方面很不错.

 

 

内核用的打印函数printk完全是和stdinstdout无关的,因为一开始到start_kernel函数刚开始进入内核就可以用printk 函数了,而建立stdinstdout是在init函数中实现的。有个问题,这里的代码中,建立stdinstdout如下

 if (open("/dev/null", O_RDWR, 0) < 0)

  printk("Warning: unable to open an initial console./n");

 (void) dup(0);

 (void) dup(0);

问题在于它打开的是/dev/null,而一般pc机上的linux打开的都是/dev/console,而且我把这几行代码删除也没有问题,所以我猜想这里建立stdinstdout并没什么用,肯定在shell中建立了定位到串口的stdinstdout。所以接下来还需要看看busybox的代码吧。

在这里还是主要分析一下printk实现的原理。

static spinlock_t logbuf_lock = SPIN_LOCK_UNLOCKED; //定义logbuf_lock,并初始化为unlock状态

static char log_buf[LOG_BUF_LEN];  //保存日志数据的缓冲区

#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])

static DECLARE_MUTEX(console_sem); //定义全局互斥信号量console_sem并初始化为1

 

asmlinkage int printk(const char *fmt, ...)

{

 va_list args;

 unsigned long flags;

 int printed_len;

 char *p;

 static char printk_buf[1024];

 static int log_level_unknown = 1;

 

 if (oops_in_progress)  // default : oops_in_progress = 0

 { //oops_in_progress指示进程发生错误,只有在panic()函数中才等于1

  //所以一般情况下下两句都不运行

 

  spin_lock_init(&logbuf_lock); //初始化logbuf_lock

 

  init_MUTEX(&console_sem); //初始化console_sem为互斥的信号量,初值为1

 }

 

 

 spin_lock_irqsave(&logbuf_lock, flags);

 //一般spin_lock在单cpu中无效的,所以spin_lock_irqsave真正的作用是关中断 和保存状态寄存器。

 

 va_start(args, fmt);

 printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);

 //先把数据格式化到printk_buf中去

 va_end(args);

 

 

 //emit_log_char 把字符存入log_buf中等待被发送,具体的参见下面的分析

 for (p = printk_buf; *p; p++) {

  if (log_level_unknown) {

   if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {

    emit_log_char('<');

    emit_log_char(default_message_loglevel + '0');

    emit_log_char('>');

   }

 //如果没有提供<1>类似的日志级别,则在此加上<4>

 //我这里的default_message_loglevel=4

   log_level_unknown = 0;

  }

  emit_log_char(*p);

  if (*p == '/n') //每一行前面都需要加<4>之类的日志级别

   log_level_unknown = 1;

 }

 

 if (!arch_consoles_callable()) // unexecute

 {

 

  spin_unlock_irqrestore(&logbuf_lock, flags);

  goto out;

 }

 if (!down_trylock(&console_sem)) //lock ok

 {

 

  spin_unlock_irqrestore(&logbuf_lock, flags);

  console_may_schedule = 0;

  release_console_sem(); //在这个函数中把数据发送到串口并释放console_sem

 } else {

  

  spin_unlock_irqrestore(&logbuf_lock, flags);

 }

out:

 return printed_len;

}

 

static unsigned long log_start; 

static unsigned long con_start; 

static unsigned long log_end; 

static unsigned long logged_chars;

static void emit_log_char(char c)

{

 LOG_BUF(log_end) = c;  //把字符c存到log_buf缓冲区中,缓冲区满了就会覆盖开始的数据

 log_end++;   //

 if (log_end - log_start > LOG_BUF_LEN) //log_start指示syslog读取的开始

  log_start = log_end - LOG_BUF_LEN;//缓冲区满了会把开始的指针向前推

 if (log_end - con_start > LOG_BUF_LEN) //con_start指示控制台读取的开始

  con_start = log_end - LOG_BUF_LEN;

 if (logged_chars < LOG_BUF_LEN)

  logged_chars++;

}

 

void release_console_sem(void)

{

 unsigned long flags;

 unsigned long _con_start, _log_end;

 unsigned long must_wake_klogd = 0;

 

 for ( ; ; ) {

  spin_lock_irqsave(&logbuf_lock, flags);//关中断和保存flag

  must_wake_klogd |= log_start - log_end; //唤醒klogd标志

  if (con_start == log_end)

   break;  

  _con_start = con_start;

  _log_end = log_end;

  con_start = log_end; 

  spin_unlock_irqrestore(&logbuf_lock, flags);

  call_console_drivers(_con_start, _log_end);//在这个函数中发送数据,见下面的分析

 }

 console_may_schedule = 0; //指示数据发送时是否能进行任务调度,在使用串口控制台时没用

 up(&console_sem); //释放信号量

 spin_unlock_irqrestore(&logbuf_lock, flags);

 if (must_wake_klogd && !oops_in_progress)

  wake_up_interruptible(&log_wait);

}

 

 

static void call_console_drivers(unsigned long start, unsigned long end)

{

 unsigned long cur_index, start_print;

 static int msg_level = -1;

 

 if (((long)(start - end)) > 0)

  BUG();

 

 cur_index = start;

 start_print = start;

 while (cur_index != end) {

  if ( msg_level < 0 &&

   ((end - cur_index) > 2) &&

   LOG_BUF(cur_index + 0) == '<' &&

   LOG_BUF(cur_index + 1) >= '0' &&

   LOG_BUF(cur_index + 1) <= '7' &&

   LOG_BUF(cur_index + 2) == '>')

  {

   msg_level = LOG_BUF(cur_index + 1) - '0';

   cur_index += 3;

   start_print = cur_index;

  } //去除每行开头的类似<4>的日志级别,把它赋给msg_level

  while (cur_index != end) {

   char c = LOG_BUF(cur_index);

   cur_index++;

   if (c == '/n') {

    if (msg_level < 0) {

     

     msg_level = default_message_loglevel;

    }

    _call_console_drivers(start_print, cur_index, msg_level);

    //发送一行数据

    msg_level = -1;

    start_print = cur_index;

    break;

   }

  }

 }

 _call_console_drivers(start_print, end, msg_level); //发送剩余的数据

}

 

 

struct console *console_drivers; //全局的console类型的结构体

 

static void _call_console_drivers(unsigned long start, unsigned long end, int msg_log_level)

{

 //如果msg_log_level < console_loglevel 并且 console_drivers存在 并且 start != end

 if (msg_log_level < console_loglevel && console_drivers && start != end) {

  if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {

  

   //缓冲区循环使用就会出现(start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)

   //的清况,于是就分两部分来发送.

   //__call_console_drivers才是真正的发送函数

   __call_console_drivers(start & LOG_BUF_MASK, LOG_BUF_LEN);

   __call_console_drivers(0, end & LOG_BUF_MASK);

  } else {

   __call_console_drivers(start, end);

  }

 }

}

 

static void __call_console_drivers(unsigned long start, unsigned long end)

{

 struct console *con;

 

 for (con = console_drivers; con; con = con->next) {

  if ((con->flags & CON_ENABLED) && con->write)

   con->write(con, &LOG_BUF(start), end - start);

 } //调用console_drivers->write来把数据发送出去

}

 

接下来理解一下console_drivers这个结构体指针

struct console

{

 char name[8];

 void (*write)(struct console *, const char *, unsigned);

 int (*read)(struct console *, const char *, unsigned);

 kdev_t (*device)(struct console *);

 int (*wait_key)(struct console *);

 void (*unblank)(void);

 int (*setup)(struct console *, char *);

 short flags;

 short index;

 int cflag;

 struct  console *next;

};

 

而开始console_drivers这个指针是NULL,在什么时候被赋值的呢,原本以为应该在用printk以前就被初始化了,其实不然,它是在start_kernel函数中调用的console_init()函数中被初始化的.最好的办法还是看看代码.

void __init console_init(void)

{

 

 memset(ldiscs, 0, sizeof(ldiscs));

 (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);

 

 

 memset(&tty_std_termios, 0, sizeof(struct termios));

 memcpy(tty_std_termios.c_cc, INIT_C_CC, NCCS);

 tty_std_termios.c_iflag = ICRNL | IXON;

 tty_std_termios.c_oflag = OPOST | ONLCR;

#ifdef CONFIG_MIZI //CONFIG_MIZI=1

 tty_std_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL;

#else

 tty_std_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL;

#endif

 tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |

  ECHOCTL | ECHOKE | IEXTEN;

 

 

#ifdef CONFIG_VT //如果不是串口控制台就定义这个虚拟控制台

 con_init(); //于是输入是键盘输出是显示器

#endif

#ifdef CONFIG_AU1000_SERIAL_CONSOLE

 au1000_serial_console_init();

#endif

#ifdef CONFIG_SERIAL_CONSOLE

#if (defined(CONFIG_8xx) || defined(CONFIG_8260))

 console_8xx_init();

#elif defined(CONFIG_MAC_SERIAL) && defined(CONFIG_SERIAL)

 if (_machine == _MACH_Pmac)

   mac_scc_console_init();

 else

  serial_console_init();

#elif defined(CONFIG_MAC_SERIAL)

  mac_scc_console_init();

#elif defined(CONFIG_PARISC)

 pdc_console_init();

#elif defined(CONFIG_SERIAL)

 serial_console_init();

#endif

#ifdef CONFIG_SGI_SERIAL

 sgi_serial_console_init();

#endif

#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC)

 vme_scc_console_init();

#endif

#if defined(CONFIG_SERIAL167)

 serial167_console_init();

#endif

#if defined(CONFIG_SH_SCI)

 sci_console_init();

#endif

#endif

#ifdef CONFIG_TN3270_CONSOLE

 tub3270_con_init();

#endif

#ifdef CONFIG_TN3215

 con3215_init();

#endif

#ifdef CONFIG_HWC

        hwc_console_init();

#endif

#ifdef CONFIG_STDIO_CONSOLE

 stdio_console_init();

#endif

#ifdef CONFIG_SERIAL_CORE_CONSOLE   //  CONFIG_SERIAL_CORE_CONSOLE=1

 uart_console_init(); //这里唯一一个被运行的函数

#endif

#ifdef CONFIG_ARC_CONSOLE

 arc_console_init();

#endif

#ifdef CONFIG_SERIAL_TX3912_CONSOLE

 tx3912_console_init();

#endif

}

 

void __init uart_console_init(void)

{

#ifdef CONFIG_SERIAL_AMBA_CONSOLE

 ambauart_console_init();

#endif

#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE

 anakin_console_init();

#endif

#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE

 clps711xuart_console_init();

#endif

#ifdef CONFIG_SERIAL_21285_CONSOLE

 rs285_console_init();

#endif

#ifdef CONFIG_SERIAL_SA1100_CONSOLE

 sa1100_rs_console_init();

#endif

#ifdef CONFIG_SERIAL_8250_CONSOLE

 serial8250_console_init();

#endif

#ifdef CONFIG_SERIAL_UART00_CONSOLE

 uart00_console_init();

#endif

#ifdef CONFIG_SERIAL_S 3C2400_CONSOLE

 s3c2400_console_init();

#endif

#ifdef CONFIG_SERIAL_S3C2410_CONSOLE

 s3c2410_console_init();  //这个函数被运行

#endif

}

 

void __init s3c2410_console_init(void)

{

 register_console(&s3c2410_cons); //调用注册控制台的函数

}

 

static struct console s3c2410_cons = {

 name:  "ttyS",

 write:  s3c2410_console_write,

 device:  s3c2410_console_device,

 wait_key: s3c2410_console_wait_key,

 setup:  s3c2410_console_setup,

 flags:  CON_PRINTBUFFER,

 index:  -1,

}; //这个就是console_drivers所指向的结构了

 

void register_console(struct console * console)

{ //该函数就是把console_drivers这个全局指针指向console结构体了,而且在注册完后

 //会把存在缓冲区中的都发送出去,所以在注册console以前调用的printk并不发送数据

 //而只是把数据存到缓冲区里,注册了以后才能被马上发送.多个控制台被注册的话就会

 //形成一个链表结构,都能发送数据.

 int     i;

 unsigned long flags;

 

 

 if (preferred_console < 0) {

  if (console->index < 0)

   console->index = 0;

  if (console->setup == NULL ||

      console->setup(console, NULL) == 0) {

   console->flags |= CON_ENABLED | CON_CONSDEV;

   preferred_console = 0;

  }

 }

 

 

 for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {

  if (strcmp(console_cmdline[i].name, console->name) != 0)

   continue;

  if (console->index >= 0 &&

      console->index != console_cmdline[i].index)

   continue;

  if (console->index < 0)

   console->index = console_cmdline[i].index;

  if (console->setup &&

      console->setup(console, console_cmdline[i].options) != 0)

   break;

  console->flags |= CON_ENABLED;

  console->index = console_cmdline[i].index;

  if (i == preferred_console)

   console->flags |= CON_CONSDEV;

  break;

 }

 

 if (!(console->flags & CON_ENABLED))

  return;

 

 

 acquire_console_sem();

 if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {

  console->next = console_drivers;

  console_drivers = console;

 } else {

  console->next = console_drivers->next;

  console_drivers->next = console;

 }

 if (console->flags & CON_PRINTBUFFER) {

 

  spin_lock_irqsave(&logbuf_lock, flags);

  con_start = log_start;

  spin_unlock_irqrestore(&logbuf_lock, flags);

 }

 release_console_sem();

}


阅读    收藏 
分类: 装修
测甲醛仪器得到结果是ppb (part per billion)

常用单位:

m

metres
g gram
mg milligrams (10-3 grams)
µg microgram (10-6 grams)
ppm parts per million (volume/volume)
ppb parts per billion (volume/volume)
mg/m3 milligrams per cubic metres
µg/m3 micrograms per cubic meter


甲醛换算:
Formaldehyde
HCHO
1 ppm = 1.2mg/m3
1mg/m3 = 0.833ppm

100 ppb = 0.1 ppm = 0.12 mg/m3.
国家标准室内0.08mg/m3 = 833 * 0.08 = 66.64 ppb。


气体浓度对大气中的污染物,常见体积浓度和质量-体积浓度来表示其在大气中的含量。, c9 X/ ~) b9 K
1、体积浓度体积浓度是用每立方米的大气中含有污染物的体积数(立方厘米)或(ml/m3)来表示,常用的表示方法是ppm,即1ppm=1立方厘米/立方米=10-6。除ppm外,还有ppb和ppt,他们之间的关系是:1ppm=10-6=一百万分之一, 1ppb=10-9=十亿分之一 ,1ppt=10-12=万亿分之一, 1ppm=103ppb=106ppt

2、质量-体积浓度用每立方米大气中污染物的质量数来表示的浓度叫质量-体积浓度,单位是毫克/立方米或克/立方米。它与ppm的换算关系是:X=M.C/22.4C=22.4X/M式中: X—污染物以每标立方米的毫克数表示的浓度值;C—污染物以ppm表示的浓度值;M—污染物的分之子量。由上式可得到如下关系:1ppm=M/22.4(mg/m3)=1000.m/22.4ug/m3例1:求在标准状态下,30毫克/标立方米的氟化氢的ppm浓度。解:氟化氢的分子量为20,则:C=30.22.4/20=33.6ppm 例2、已知大气中二氧化硫的浓度为5ppm,求以mg/Nm3表示的浓度值。解:二氧化硫的分子量为64。X =5.64/22.4mg/m3=14.3mg/m3' i$ ^6 e0


引用:
1. http://ww2.unhabitat.org/wuf/2006/aqm/tool28.htm
2. http://bbs.hcbbs.com/thread-779007-1-1.html
阅读    收藏 
标签:

shear-warp

c

代码

分类: 算法

根据硬件计算的架构,用C++建立了一个软件模型,证明硬件计算的可行性。

Shear之后的图像,C++结果:

 

http://s1/middle/679f93564bc33ebdb6710&amp;690

 

MatLab Shear结果:

 

http://s1/middle/679f93564bc33ebdb9110&amp;690

 

Warp结果,C++:

 

http://s10/middle/679f93564bc33ebea3429&amp;690

 

MatLab Warp结果:

 

http://s14/middle/679f93564bc33ebf1533d&amp;690

 

//shear-warp sw model

//zf2266#mail.ustc.edu.cn, Zhanxiang Zhao

 

#include <iostream>

#include <fstream>

#include "windows.h"

#include "math.h"

 

using std::endl;

using std::cout;

using std::cin;

 

#define LINE_LENGTH 81

#define LINE_SHEAR_LENGTH int(LINE_LENGTH*1.7321+2)

#define ALPHA_TABLE_SIZE 1000

#define DIM 4

#define IMAGE_SIZE 400

 

double volume[LINE_LENGTH][LINE_LENGTH][LINE_LENGTH];

double lineBuf[5][LINE_LENGTH];

double shearedBuf[LINE_SHEAR_LENGTH];

double interImgBuf[LINE_SHEAR_LENGTH*LINE_SHEAR_LENGTH];

double renderImage[IMAGE_SIZE*IMAGE_SIZE];

double alphaTable[ALPHA_TABLE_SIZE];

double Mview[DIM*DIM];

double Mshear[DIM*DIM];

double Mwarp[(DIM-1)*(DIM-1)];

double MshearInv[DIM*DIM];

double MwarpInv[(DIM-1)*(DIM-1)];

 

 

struct LUPMat

{

    double* L, *U, *P; //dim*dim

    int* pai; //dim

    int dim; //dimension of LUP, size is d*d

};

 

void DelLUPMat( LUPMat lm)

{

    delete [] lm.L;

    delete [] lm.U;

    delete [] lm.P;

    delete [] lm.pai;

}

 

void printMatrix(double* mat, int dim)

{

    for(int i=0; i<dim; i++)

    {

        for(int j=0; j<dim; j++)

            printf("%2.5f ", mat[i*dim+j]);

        printf("\n");

    }

}

 

void printVector(double* vec, int dim)

{

    for(int i=0; i<dim; i++)

    {

        printf("%2.2f ", vec[i]);

    }

    printf("\n");

}

 

 

//LUP decomposition of dim*dim matrix

LUPMat LUPDecomp(double *A, int dim)

{

    double* mat = new double[dim*dim];

    for(int i=0; i<dim; i++)

        for(int j=0; j<dim; j++)

            mat[i*dim+j] = A[i*dim+j];

    double* l = new double[dim*dim];

    double* u = new double[dim*dim];

    double* p = new double[dim*dim];

    int* pai = new int[dim]; //pai[i]=k, then p[i][k]=1

    for(int i=0; i<dim; i++)

        pai[i] = i;

    double cmax; //max value of column

    int maxLineNo; //line of cmax

    for(int k=0; k<dim; k++)

    {

        //find max value of the k-th column

        cmax=0;

        for(int i=k; i<dim; i++)

        {

            if(abs(mat[i*dim+k])>abs(cmax))

            {

                cmax = mat[i*dim+k];

                maxLineNo = i;

            }

        }

        if(cmax==0)

        {

            printf("singular matrix!\n");

            exit(1);

        }

        int tmpk = pai[k];

        pai[k] = pai[maxLineNo];

        pai[maxLineNo] = tmpk;

        double tmpLn;

        //exchange line

        for(int li=0; li<dim; li++)

        {

            tmpLn = mat[k*dim+li];

            mat[k*dim+li] = mat[maxLineNo*dim+li];

            mat[maxLineNo*dim+li] = tmpLn;

        }

        //LU decomposition

        for(int i=k+1; i<dim; i++)

        {

            mat[i*dim+k] = mat[i*dim+k]/mat[k*dim+k];

            for(int j=k+1; j<dim; j++)

                mat[i*dim+j] = mat[i*dim+j] - mat[i*dim+k]*mat[k*dim+j];

        }

    }

    for(int i=0; i<dim; i++)

    {

        for(int j=0; j<dim; j++)

        {

            if(i>j)

            {

                l[i*dim+j] = mat[i*dim+j];

                u[i*dim+j] = 0;

            }

            else if(i==j)

            {

                u[i*dim+j] = mat[i*dim+j];

                l[i*dim+j] = 1;

            }

            else

            {

                u[i*dim+j] = mat[i*dim+j];

                l[i*dim+j] = 0;

            }

        }

    }

    for(int i=0; i<dim; i++)

    {

        for(int j=0; j<dim; j++)

            p[i*dim+j] = 0;

        p[i*dim+pai[i]] = 1;

    }

    LUPMat ret;

    ret.L = l;

    ret.U = u;

    ret.P = p;

    ret.pai = pai;

    ret.dim = dim;

    delete [] mat;

    return ret;

}

 

//testbench

void LUPDecomp_tb()

{

    double mat[DIM*DIM] = {

        2, 0, 2, 0.6,

        3, 3, 4, -2,

        5, 5, 4, 2,

        -1, -2, 3.4, -1};

        printMatrix(mat, DIM);

        LUPMat lm = LUPDecomp(mat, DIM);

 

        cout<<"P = "<<endl;

        printMatrix(lm.P, DIM);

 

        cout<<"L = "<<endl;

        printMatrix(lm.L, DIM);

 

        cout<<"U = "<<endl;

        printMatrix(lm.U, DIM);

        DelLUPMat(lm);

}

 

 

double *SolveLinearEq(double* A, double* b, int dim)

{

    LUPMat lm = LUPDecomp(A, dim);

    double* x = new double[dim];

    double* y = new double[dim];

    for(int i=0; i<dim; i++)

    {

        y[i] = b[lm.pai[i]];

        for(int j=0; j<i; j++)

            y[i] -= y[j]*lm.L[i*dim+j];

    }

    //cout<<"y:"<<endl;

    //    printVector(y, dim);

    for(int i=dim-1; i>=0; i--)

    {

        for(int j=dim-1; j>i; j--)

            y[i] -= lm.U[i*dim+j]*x[j];

        x[i] = y[i]/lm.U[i*dim+i];

    }    

    //cout<<"y:"<<endl;

    //    printVector(y, dim);

    delete [] y;

    DelLUPMat(lm);

    return x;

}

 

void SolveLinearEq_tb()

{

    const int dim=3;

    double A[dim*dim] =

    {1, 2, 0,

    3, 4, 4,

    5, 6, 3};

    cout<<"A: "<<endl;

    printMatrix(A, dim);

    double b[dim] ={3, 7, 8};

    double* x = SolveLinearEq(A, b, dim);

    cout<<"x: "<<endl;

    printVector(x, dim);

    delete [] x;

}

 

double* InverseMatrix(double *A, int dim)

{

    double *invA = new double[dim*dim];

    double *e = new double[dim];

    double *x;

    for(int i=0; i<dim; i++)

        e[i] = 0;

 

    for(int i=0; i<dim; i++)

    {

        e[i] = 1;

        if(i>0) e[i-1]=0;

        x = SolveLinearEq(A, e, dim);

        //    cout<<"No. "<<i<<" x: ";

        //    printVector(x, dim);

        //    cout<<"e: ";

        //    printVector(e, dim);

        for(int j=0; j<dim; j++)

            invA[j*dim+i] = x[j];

    }

    delete [] x;

    return invA;

}

 

//matrix multiply

double* MatMult(double* A, double* invA, int dim)

{

    double* aij = new double[dim*dim];

    for(int i=0; i<dim; i++)

        for(int j=0; j<dim; j++)

        {

            aij[i*dim+j]=0;

            for(int k=0; k<dim; k++)

                aij[i*dim+j] += A[i*dim+k]*invA[k*dim+j];

        }

        return aij;

}

 

void InverseMatrix_tb()

{

    const int dim=3;

    double A[dim*dim] =

    {1, 2, 0,

    3, 4, 4,

    5, 6, 3};

    cout<<"A: "<<endl;

    printMatrix(A, dim);

    double* invA = InverseMatrix(A, dim);

    cout<<"inverse of A: "<<endl;

    printMatrix(invA, dim);

    double* aij = MatMult(A, invA, dim);

    cout<<"A*invA:"<<endl;

    printMatrix(aij, dim);

    delete [] invA;

    delete [] aij;

}

 

void copyMatrix2D(double* src, double* des, int dim)

{

    for(int i=0; i<dim; i++)

        for(int j=0; j<dim; j++)

            des[i*dim+j] = src[i*dim+j];

}

 

//compute shear warp matrix

//return principle viewing axis: c

int MakeShearWarpMat()

{

    //Find the principal viewing axis

    double Vo[DIM-1] ={

        Mview[0*DIM+1]*Mview[1*DIM+2] - Mview[1*DIM+1]*Mview[0*DIM+2],

        Mview[1*DIM+0]*Mview[0*DIM+2] - Mview[0*DIM+0]*Mview[1*DIM+2],

        Mview[0*DIM+0]*Mview[1*DIM+1] - Mview[1*DIM+0]*Mview[0*DIM+1]

    };

 

    double maxv=Vo[0];

    int c=0;

    for(int i=1; i<DIM-1; i++)

    {

        if(Vo[i]>maxv)

        {    

            maxv=Vo[i];

            c=i;

        }

    }

    // Choose the corresponding Permutation matrix P

    double pyzx[DIM*DIM] = {0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1};

    double pzxy[DIM*DIM] = {0,0,1,0, 1,0,0,0, 0,1,0,0, 0,0,0,1};

    double pxyz[DIM*DIM] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};

    double* p;

    double P[DIM*DIM];

 

    if(c==0)

        p = pyzx;

    else if(c==1)

        p = pzxy;

    else    //2

        p = pxyz;

    copyMatrix2D(p, P, DIM);

 

    //Compute the permuted view matrix from Mview and P    

    double* invP = InverseMatrix(P, DIM);

    //xiangge

    cout<<"inv P:"<<endl;

    printMatrix(invP, DIM);

    double* Mview_p = MatMult(Mview, invP, DIM);

    //xiangge

    cout<<"inv(Mview_p):"<<endl;

    printMatrix(Mview_p, DIM);

    delete [] invP;

    //180 degrees rotate detection

    if(Mview_p[2*DIM+2]<0) c=c+3;

 

    //Compute the shear coeficients from the permuted view matrix

    double Si = (Mview_p[1*DIM+1]* Mview_p[0*DIM+2] - Mview_p[0*DIM+1]* Mview_p[1*DIM+2]) / (Mview_p[0*DIM+0]* Mview_p[1*DIM+1] - Mview_p[1*DIM+0]* Mview_p[0*DIM+1]);

    double Sj = (Mview_p[0*DIM+0]* Mview_p[1*DIM+2] - Mview_p[1*DIM+0]* Mview_p[0*DIM+2]) / (Mview_p[0*DIM+0]* Mview_p[1*DIM+1] - Mview_p[1*DIM+0]* Mview_p[0*DIM+1]);

    double Ti, Tj;

    // Compute the translation between the orgins of standard object coordinates

    // and intermdiate image coordinates

    double kmax = LINE_LENGTH-1;

    if ((Si>=0)&&(Sj>=0)){ Ti = 0; Tj = 0; }

    if ((Si>=0)&&(Sj<0)){ Ti = 0; Tj = -Sj*kmax; }

    if ((Si<0)&&(Sj>=0)){ Ti = -Si*kmax; Tj = 0; }

    if ((Si<0)&&(Sj<0)){ Ti = -Si*kmax; Tj = -Sj*kmax; }

 

    // Compute the shear matrix

    double mshear[DIM*DIM]=

    {

        1, 0, Si, Ti,

        0, 1, Sj, Tj,

        0, 0, 1 ,0 ,

        0, 0, 0 ,1

    };

    copyMatrix2D(mshear, Mshear, DIM);

 

    // Compute the 2Dwarp matrix

    double mwarp[(DIM-1)*(DIM-1)]={

        Mview_p[0*DIM+0], Mview_p[0*DIM+1], (Mview_p[0*DIM+3]-Ti*Mview_p[0*DIM+0]-Tj*Mview_p[0*DIM+1]),

        Mview_p[1*DIM+0], Mview_p[1*DIM+1], (Mview_p[1*DIM+3]-Ti*Mview_p[1*DIM+0]-Tj*Mview_p[1*DIM+1]),

        0, 0, 1

    };

    copyMatrix2D(mwarp, Mwarp, DIM-1);

    return c;

}

 

//bilinear interpolation of 4 points

double Interp(double* intensity, double* perc)

{

    double result=0.0f;

    for(int i=0; i<4; i++)

        result += intensity[i] * perc[i];

    //Attention: should not use: *intensity++ * *perc++,

    //for system can delete array normally without the change of pointer

    return result;

}

 

//

void Shear()

{

    cout<<"Start Shear"<<endl;

    double* invshear = InverseMatrix(Mshear, DIM);

    copyMatrix2D(invshear, MshearInv, DIM);

    double* invwarp = InverseMatrix(Mwarp, DIM-1);

    copyMatrix2D(invwarp, MwarpInv, DIM-1);

    cout<<"MshearInv:"<<endl;

    printMatrix(MshearInv, DIM);

    cout<<"MwarpInv:"<<endl;

    printMatrix(MwarpInv, DIM-1);

    delete [] invshear;

    delete [] invwarp;

    //c=0

    int py[LINE_LENGTH-1];

    int px[LINE_LENGTH-1];

    for(int z=0; z<(LINE_LENGTH-1); z++)

    {

        cout<<"Shear Slice "<<z+1<<endl;

        //Offset calculation

        double xd=(0-(double)LINE_SHEAR_LENGTH/2)+MshearInv[0*DIM+2]*((double)z-(double)LINE_LENGTH/2)+(double)LINE_LENGTH/2;

        double yd=(0-(double)LINE_SHEAR_LENGTH/2)+MshearInv[1*DIM+2]*((double)z-(double)LINE_LENGTH/2)+(double)LINE_LENGTH/2;

 

        double xdfloor=floor(xd);

        double ydfloor=floor(yd);

 

        //calculate the coordinates on which a image slice starts and

        //ends in the temporary shear image (buffer)

        double pystart=-ydfloor;

        if(pystart<0) pystart=0;

        double pyend = LINE_LENGTH-ydfloor;

        if(pyend>LINE_SHEAR_LENGTH) pyend=LINE_SHEAR_LENGTH;

 

        double pxstart=-xdfloor;

        if(pxstart<0) pxstart=0;

        double pxend = LINE_LENGTH-xdfloor;

        if(pxend>LINE_SHEAR_LENGTH) pxend=LINE_SHEAR_LENGTH;

 

        int npy = pyend-pystart-1;

        int npx = pxend-pxstart-1;

        py[0] = pystart;

        for(int i=1; i<npy; i++)

            py[i] = py[i-1]+1;

        px[0] = pxstart;

        for(int i=1; i<npx; i++)

            px[i] = px[i-1]+1;

        //Linear interpolation constants (percentages)

        double xCom=xd-floor(xd);

        double yCom=yd-floor(yd);

        double perc[4]={(1-xCom)*(1-yCom), (1-xCom)*yCom, xCom*(1-yCom), xCom*yCom};

        double intensity_loc;

        double intensityInterp[4];

        double alphaimage;

        double alphaimage_inv;

        double shearedimage;

        int indexAlpha;

 

        //Determine x and y coordinates of pixel(s) which will be come current pixel

        //bilinear

        for(int iy=0; iy<npy-1; iy++)

        {

            for(int ix=0; ix<npx-1; ix++)

            {

                intensityInterp[0] = volume[z][int(px[ix])+int(xdfloor)][int(py[iy])+int(ydfloor)];

                intensityInterp[1] = volume[z][int(px[ix])+int(xdfloor)][int(py[iy])+int(ydfloor)+1];

                intensityInterp[2] = volume[z][int(px[ix])+int(xdfloor)+1][int(py[iy])+int(ydfloor)];

                intensityInterp[3] = volume[z][int(px[ix])+int(xdfloor)+1][int(py[iy])+int(ydfloor)+1];

                intensity_loc = Interp(intensityInterp, perc);

                //calculate current alphaimage

                indexAlpha = floor(intensity_loc*(ALPHA_TABLE_SIZE-1)+0.5)+1;

                alphaimage=alphaTable[indexAlpha];

                alphaimage_inv=(1-alphaimage);

                //Update the current pixel in the shear image buffer

                interImgBuf[int(px[ix])*LINE_SHEAR_LENGTH+int(py[iy])]=alphaimage_inv*interImgBuf[int(px[ix])*LINE_SHEAR_LENGTH+int(py[iy])]+alphaimage*intensity_loc;

            }

        }

        cout<<"sheared intermediate image: "<<endl;

        std::ofstream ofShear("shearImg.dat");

        for(int i=0; i<LINE_SHEAR_LENGTH; i++)

        {

            for(int j=0; j<LINE_SHEAR_LENGTH; j++)

                ofShear<<interImgBuf[i*LINE_SHEAR_LENGTH+j]<<" ";

            ofShear<<endl;

        }

        ofShear.close();

    }

    cout<<"exit shear"<<endl;

}

 

//set x to boundary

void setBoundary(double &x, double floor, double ceil)

{

    if(x<floor) x=floor;

    if(x>ceil-1) x=ceil-1;

}

 

//

void Warp()

{

    //format the output image

    for(int i=0; i<IMAGE_SIZE; i++)

    {

        for(int j=0; j<IMAGE_SIZE; j++)

        {

            renderImage[i*IMAGE_SIZE+j] = 0;

        }

    }

    cout<<"start Warp"<<endl;

    double *Tlocalx = new double[IMAGE_SIZE*IMAGE_SIZE];

    double *Tlocaly = new double[IMAGE_SIZE*IMAGE_SIZE];

    double *xbas = new double[IMAGE_SIZE*IMAGE_SIZE];

    double *ybas = new double[IMAGE_SIZE*IMAGE_SIZE];

    double *tx = new double[IMAGE_SIZE*IMAGE_SIZE];

    double *ty = new double[IMAGE_SIZE*IMAGE_SIZE];

    //center of output image

    double mean_out = IMAGE_SIZE/2;

    //center of input image

    double mean_in = LINE_SHEAR_LENGTH/2;

 

    double percInterp[4];

    double imageInterp[4];    

    bool check_xbas0, check_ybas0, check_xbas1, check_ybas1;

    for(int i=0; i<IMAGE_SIZE; i++)

    {

        for(int j=0; j<IMAGE_SIZE; j++)

        {

            //center of output image coordinates is (0,0)

            double xd = i-mean_out;

            double yd = j-mean_out;

 

            //Calculate the Transformed coordinates

            Tlocalx[i*IMAGE_SIZE+j] = mean_in + MwarpInv[0*(DIM-1)+0]*xd + MwarpInv[0*(DIM-1)+1]*yd + (MwarpInv[0*(DIM-1)+2]+MshearInv[0*DIM+3]) * 1;

            Tlocaly[i*IMAGE_SIZE+j] = mean_in + MwarpInv[1*(DIM-1)+0]*xd + MwarpInv[1*(DIM-1)+1]*yd + (MwarpInv[1*(DIM-1)+2]+MshearInv[1*DIM+3]) * 1;

 

            //Interp coordinates

            xbas[i*IMAGE_SIZE+j] = floor(Tlocalx[i*IMAGE_SIZE+j]);

            ybas[i*IMAGE_SIZE+j] = floor(Tlocaly[i*IMAGE_SIZE+j]);

            tx[i*IMAGE_SIZE+j] = Tlocalx[i*IMAGE_SIZE+j] - xbas[i*IMAGE_SIZE+j];

            ty[i*IMAGE_SIZE+j] = Tlocaly[i*IMAGE_SIZE+j] - ybas[i*IMAGE_SIZE+j];

        }

    }

    for(int i=0; i<IMAGE_SIZE-1; i++)

    {

        for(int j=0; j<IMAGE_SIZE-1; j++)

        {

            percInterp[0] = (1-tx[i*IMAGE_SIZE+j])*(1-ty[i*IMAGE_SIZE+j]);

            percInterp[1] = (1-tx[i*IMAGE_SIZE+j])*ty[i*IMAGE_SIZE+j];

            percInterp[2] = tx[i*IMAGE_SIZE+j]*(1-ty[i*IMAGE_SIZE+j]);

            percInterp[3] = tx[i*IMAGE_SIZE+j]*ty[i*IMAGE_SIZE+j];

            

            //limit indices to boundaries

            check_xbas0 = xbas[i*IMAGE_SIZE+j]<0 || xbas[i*IMAGE_SIZE+j]>(LINE_SHEAR_LENGTH-1);

            check_ybas0 = ybas[i*IMAGE_SIZE+j]<0 || ybas[i*IMAGE_SIZE+j]>(LINE_SHEAR_LENGTH-1);

            check_xbas1 = (xbas[i*IMAGE_SIZE+j]+1)<0 || (xbas[i*IMAGE_SIZE+j]+1)>(LINE_SHEAR_LENGTH-1);

            check_ybas1 = (ybas[i*IMAGE_SIZE+j]+1)<0 || (ybas[i*IMAGE_SIZE+j]+1)>(LINE_SHEAR_LENGTH-1);

 

            //set to boundary

            setBoundary(xbas[i*IMAGE_SIZE+j], 0, LINE_SHEAR_LENGTH);

            setBoundary(xbas[i*IMAGE_SIZE+j], -1, LINE_SHEAR_LENGTH-1); //xbas[i]+1

            setBoundary(ybas[i*IMAGE_SIZE+j], 0, LINE_SHEAR_LENGTH);

            setBoundary(ybas[i*IMAGE_SIZE+j], -1, LINE_SHEAR_LENGTH-1);

 

            imageInterp[0] = interImgBuf[int(xbas[i*IMAGE_SIZE+j])*LINE_SHEAR_LENGTH+int(ybas[i*IMAGE_SIZE+j])];

            imageInterp[1] = interImgBuf[int(xbas[i*IMAGE_SIZE+j])*LINE_SHEAR_LENGTH+int(ybas[i*IMAGE_SIZE+j]+1)];

            imageInterp[2] = interImgBuf[int(xbas[i*IMAGE_SIZE+j]+1)*LINE_SHEAR_LENGTH+int(ybas[i*IMAGE_SIZE+j])];

            imageInterp[3] = interImgBuf[int(xbas[i*IMAGE_SIZE+j]+1)*LINE_SHEAR_LENGTH+int(ybas[i*IMAGE_SIZE+j]+1)];

            

            imageInterp[0] = (check_xbas0 || check_ybas0) ? 0 : imageInterp[0];

            imageInterp[1] = (check_xbas0 || check_ybas1) ? 0 : imageInterp[1];

            imageInterp[2] = (check_xbas1 || check_ybas0) ? 0 : imageInterp[2];

            imageInterp[3] = (check_xbas0 || check_ybas1) ? 0 : imageInterp[3];

 

            renderImage[i*IMAGE_SIZE+j] = Interp(imageInterp, percInterp);

        }

    }

    delete [] Tlocalx ;

    delete [] Tlocaly ;

    delete [] xbas ;

    delete [] ybas ;

    delete [] tx ;

    delete [] ty ;

    cout<<"exit Warp"<<endl;

}

 

//

bool render(const char* volumefile, const char* alphafile)

{

    for(int i=0; i<LINE_SHEAR_LENGTH; i++)

    {

        for(int j=0; j<LINE_SHEAR_LENGTH; j++)

            interImgBuf[i*LINE_SHEAR_LENGTH+j]=0;

    }

    for(int i=0; i<LINE_LENGTH; i++)

    {

        for(int j=0; j<LINE_LENGTH; j++)

            renderImage[i*LINE_LENGTH+j]=0;

    }

    std::ifstream ifVolume(volumefile);

    if(ifVolume.fail())

    {

        cout<<"unable to open volume file!"<<endl;

        return false;

    }

    //read volume

    for(int i=0; i<LINE_LENGTH; i++)

        for(int j=0; j<LINE_LENGTH; j++)

            for(int k=0; k<LINE_LENGTH; k++)

            {

                ifVolume>>volume[i][j][k];

            }

    ifVolume.close();

    std::ifstream ifAlpha(alphafile);

    if(ifAlpha.fail())

    {

        cout<<"unable to open alpha table file!"<<endl;

        return false;

    }

    //read alpha table

    for(int i=0; i<ALPHA_TABLE_SIZE; i++)

        ifAlpha>>alphaTable[i];

    ifAlpha.close();

    int c=MakeShearWarpMat();

    cout<<"Mshear:"<<endl;

    printMatrix(Mshear, DIM);

    cout<<"Mwarp:"<<endl;

    printMatrix(Mwarp, DIM-1);

    Shear();

    Warp();

    std::ofstream ofImage("render.dat");

    for(int i=0; i<IMAGE_SIZE; i++)

    {

        for(int j=0; j<IMAGE_SIZE; j++)

            ofImage<<renderImage[i*IMAGE_SIZE+j]<<" ";

        ofImage<<endl;

    }

    ofImage.close();

}

 

int main()

{

    double mview[DIM*DIM]=

{     0.6783, 1.6190, -0.2468, 0,

0.9310, -0.1614, 1.4998, 0,

1.3473, -0.7035, -0.9121, 0,

0, 0, 0, 1.0000

    };

    copyMatrix2D(mview, Mview, DIM);

    const char* volumefile = "volume.dat";

    const char* alphafile = "alphatable.dat";

    render(volumefile, alphafile);

    system("pause");

}

阅读    收藏 
标签:

xil_printf

printf

sdk

xilinx

microblaze

it

分类: 硬件

在xilinx SDK基于microblaze测试pcie示例程序一直不能run,简单的下面代码


printf("x=%8.8x\n", x);
xil_printf("x=%8.8x\n", x);

 

第一个就不能运行,第二个就可以。很奇怪。

 

http://www.eefocus.com/walkie/blog/09-02/165549_bf04c.html

这篇文章讲了一些区别,但没解释我看到的现象。

阅读    收藏 
(2012-03-14 22:53)
标签:

矩阵

求逆

c

cpp

lup分解

分类: 算法

按照算法导论上矩阵求逆的原理,写了个C++代码。

有A*X=I,则X为inv(A)。

  1. 用高斯消元法对原矩阵LUP分解,使得PA=LU。P为置换矩阵,为了使每次消元时取有列最大值的行。L下三角阵,U上三角阵。
  2. 根据分解结果求出线性方程组A*xi=ei的xi向量,ei是单位阵I的列向量i,则xi为X的对应列向量。
  3. 把xi组合成X,即为逆矩阵。

     

struct LUPMat

{

    float* L, *U, *P; //dim*dim

    int* pai; //dim

    int dim; //dimension of LUP, size is d*d

};

 

void DelLUPMat( LUPMat lm)

{

    delete [] lm.L;

    delete [] lm.U;

    delete [] lm.P;

    delete [] lm.pai;

}

 

void printMatrix(float* mat, int dim)

{

    for(int i=0; i<dim; i++)

    {

        for(int j=0; j<dim; j++)

            printf("%2.2f ", mat[i*dim+j]);

        printf("\n");

    }

}

 

void printVector(float* vec, int dim)

{

    for(int i=0; i<dim; i++)

    {

        printf("%2.2f ", vec[i]);

    }

        printf("\n");

}

 

 

//LUP decomposition of dim*dim matrix

LUPMat LUPDecomp(float *A, int dim)

{

    float* mat = new float[dim*dim];

    for(int i=0; i<dim; i++)

        for(int j=0; j<dim; j++)

            mat[i*dim+j] = A[i*dim+j];

    float* l = new float[dim*dim];

    float* u = new float[dim*dim];

    float* p = new float[dim*dim];

    int* pai = new int[dim]; //pai[i]=k, then p[i][k]=1

    for(int i=0; i<dim; i++)

        pai[i] = i;

    float cmax; //max value of column

    int maxLineNo; //line of cmax

    for(int k=0; k<dim; k++)

    {

        //find max value of the k-th column

        cmax=0;

        for(int i=k; i<dim; i++)

        {

            if(abs(mat[i*dim+k])>abs(cmax))

            {

                cmax = mat[i*dim+k];

                maxLineNo = i;

            }

        }

        if(cmax==0)

        {

            printf("singular matrix!\n");

            exit(1);

        }

        int tmpk = pai[k];

        pai[k] = pai[maxLineNo];

        pai[maxLineNo] = tmpk;

        float tmpLn;

        //exchange line

        for(int li=0; li<dim; li++)

        {

            tmpLn = mat[k*dim+li];

            mat[k*dim+li] = mat[maxLineNo*dim+li];

            mat[maxLineNo*dim+li] = tmpLn;

        }

        //LU decomposition

        for(int i=k+1; i<dim; i++)

        {

            mat[i*dim+k] = mat[i*dim+k]/mat[k*dim+k];

            for(int j=k+1; j<dim; j++)

                mat[i*dim+j] = mat[i*dim+j] - mat[i*dim+k]*mat[k*dim+j];

        }

    }

    for(int i=0; i<dim; i++)

    {

        for(int j=0; j<dim; j++)

        {

            if(i>j)

            {

                l[i*dim+j] = mat[i*dim+j];

                u[i*dim+j] = 0;

            }

            else if(i==j)

            {

                u[i*dim+j] = mat[i*dim+j];

                l[i*dim+j] = 1;

            }

            else

            {

                u[i*dim+j] = mat[i*dim+j];

                l[i*dim+j] = 0;

            }

        }

    }

    for(int i=0; i<dim; i++)

    {

        for(int j=0; j<dim; j++)

            p[i*dim+j] = 0;

        p[i*dim+pai[i]] = 1;

    }

    LUPMat ret;

    ret.L = l;

    ret.U = u;

    ret.P = p;

    ret.pai = pai;

    ret.dim = dim;

    delete [] mat;

    return ret;

}

 

//testbench

void LUPDecomp_tb()

{

    float mat[DIM*DIM] = {

        2, 0, 2, 0.6,

        3, 3, 4, -2,

        5, 5, 4, 2,

        -1, -2, 3.4, -1};

    printMatrix(mat, DIM);

    LUPMat lm = LUPDecomp(mat, DIM);

 

    cout<<"P = "<<endl;

    printMatrix(lm.P, DIM);

 

    cout<<"L = "<<endl;

    printMatrix(lm.L, DIM);

 

    cout<<"U = "<<endl;

    printMatrix(lm.U, DIM);

    DelLUPMat(lm);

}

 

 

float *SolveLinearEq(float* A, float* b, int dim)

{

    LUPMat lm = LUPDecomp(A, dim);

    float* x = new float[dim];

    float* y = new float[dim];

    for(int i=0; i<dim; i++)

    {

        y[i] = b[lm.pai[i]];

        for(int j=0; j<i; j++)

            y[i] -= y[j]*lm.L[i*dim+j];

    }

    //cout<<"y:"<<endl;

    printVector(y, dim);

    for(int i=dim-1; i>=0; i--)

    {

        for(int j=dim-1; j>i; j--)

            y[i] -= lm.U[i*dim+j]*x[j];

        x[i] = y[i]/lm.U[i*dim+i];

    }    

    //cout<<"y:"<<endl;

    printVector(y, dim);

    delete [] y;

    DelLUPMat(lm);

    return x;

}

 

void SolveLinearEq_tb()

{

    const int dim=3;

    float A[dim*dim] =

    {1, 2, 0,

     3, 4, 4,

     5, 6, 3};

    cout<<"A: "<<endl;

    printMatrix(A, dim);

    float b[dim] ={3, 7, 8};

    float* x = SolveLinearEq(A, b, dim);

    cout<<"x: "<<endl;

    printVector(x, dim);

    delete [] x;

}

 

float* InverseMatrix(float *A, int dim)

{

    float *invA = new float[dim*dim];

    float *e = new float[dim];

    float *x;

    for(int i=0; i<dim; i++)

        e[i] = 0;

 

    for(int i=0; i<dim; i++)

    {

        e[i] = 1;

        if(i>0) e[i-1]=0;

        x = SolveLinearEq(A, e, dim);

    //    cout<<"No. "<<i<<" x: ";

        printVector(x, dim);

    //    cout<<"e: ";

        printVector(e, dim);

        for(int j=0; j<dim; j++)

            invA[j*dim+i] = x[j];

    }

    delete [] x;

    return invA;

}

 

float* isInverse(float* A, float* invA, int dim)

{

    float* aij = new float[dim*dim];

    for(int i=0; i<dim; i++)

        for(int j=0; j<dim; j++)

        {

            aij[i*dim+j]=0;

            for(int k=0; k<dim; k++)

                aij[i*dim+j] += A[i*dim+k]*invA[k*dim+j];

        }

    return aij;

}

 

void InverseMatrix_tb()

{

    const int dim=3;

    float A[dim*dim] =

    {1, 2, 0,

     3, 4, 4,

     5, 6, 3};

    cout<<"A: "<<endl;

    printMatrix(A, dim);

    float* invA = InverseMatrix(A, dim);

    cout<<"inverse of A: "<<endl;

    printMatrix(invA, dim);

    float* aij = isInverse(A, invA, dim);

    cout<<"A*invA:"<<endl;

    printMatrix(aij, dim);

    delete [] invA;

    delete [] aij;

}

 

测试程序的结果:

 

http://s7/middle/679f93564bb3523c25716&amp;690

阅读    收藏 
标签:

cmut

压电陶瓷

超声换能器

分类: 医疗成像

作为新型的二维超声换能器阵列,CMUT阵列相比原来的二维压电陶瓷换能器阵列有什么优势呢,我们来看一篇论文:引文1,斯坦福大学Omer Oralkan等人通过CMUT换能器与压电陶瓷换能器的实验比较,测试了CMUT的性能。里面比较了CMUT与二维压电陶瓷换能器。

 

二维压电陶瓷换能器缺点:

  1. 要制造很多阵元困难,连线复杂;
  2. 栅瓣。为了减少栅瓣,阵元间距必须小于声波波长,(声速1540m/s,频率5MHz时,波长308 um;10MHz,154um;频率高,探测精度高)这种小尺寸对与压电陶瓷材料限制了发射能量并降低了接收灵敏度,很难达到较大的动态范围。

 

而CMUT优势:

  1. 更好带宽;
  2. 灵敏度高;
  3. 易于制造;
  4. 尺寸小;
  5. 自身噪声低;
  6. 还可以与CMOS IC集成封装。

论文中用直径36um CMUT和400us*400um压电换能器做实验。下图为压电陶瓷PZT与CMUT灵敏度比较,相比CMUT 200% Cp(寄生电容)模型,压电陶瓷只在中心频率3MHz附近有优势。通过把接收放大器集成到CMUT芯片上,可以降低寄生电容。

http://s16/middle/679f93564baf73bbd0e0f&amp;690

 

二者信噪比比较,压电陶瓷只在中心频率3MHz附近有优势。

http://s13/middle/679f93564baf73bd2878c&amp;690

 

Reference

[1] O. Oralkan, X. Jin, F. L.Degertekin, and B. T.Khuri-Yakub, "Simulation and experimental characterization of a 2-D capacitive micromachined ultrasonic transducer array element," IEEE Trans. Ultrason. Ferroelect. Freq. Contr., vol. 46, pp. 1337–1340, Nov. 1999.

阅读    收藏 
标签:

field

ii

医疗超声成像

建模

matlab

分类: 医疗成像

昨天开组会大家讨论问题,有几个疑问被提出来了:

  1. Field II主要建模算法用C代码实现。

     

  2. 二维压电陶瓷换能器阵列和CMUT二维换能器阵列有什么区别?

     

    本文只讨论第一个问题,第二个另文细述。

     

Field II代码

 

和大二小师弟讨论Field II建模CMUT换能器时,发现Field II的Matlab代码只是来做参数配置和调用函数的,这些函数编译为可执行文件,主要的建模算法是用C代码实现,而这个代码并没有开源。我给Dr. Jensen发了封邮件要C代码,但愿能回复我。

 

建模方法

 

使用空间冲击响应(spatial impulse response)的原理,依托于超声场的线性系统理论。发射时,当换能器被狄拉克delta函数激发后,空间中每个点的声场是关于时间的函数。声场可以通过空间冲激响应和激发函数卷积得到。接收时,把换能器激发函数和发射孔径的空间冲击响应、接受孔径的空间冲击响应卷积得到接收响应,通过换能器的机械电子传递函数得到接收电压曲线。

 

软件使用

 

如果只是用Field II仿真声场,可以直接调用Matlab函数,配置参数,比如探头的物理参数(阵元类型,数量,尺寸,探测物,接收孔径等),然后得到接收信号,可以拿来波束合成。我们用一段示例程序来产生血流的接收波束信号如图。

http://s13/middle/679f93564baf697eb57fc&amp;690

 

% This examples shows how the procedures can be used for making flow data from a number of scatters in a tube.

% Example of use of the new Field II program running under Matlab

%

% This example shows how flow can simulated

%

% This script assumes that the field_init procedure has been called

%

% Example by Joergen Arendt Jensen, March 22, 2011.

% Generate the transducer apertures for send and receive

f0=3e6; % Transducer center frequency [Hz]

fs=100e6; % Sampling frequency [Hz]

c=1540; % Speed of sound [m/s],人体内声音平均速度

lambda=c/f0; % Wavelength

element_height=5/1000; % Height of element [m]

kerf=0.1/1000; % Kerf [m]

focus=[0 0 70]/1000; % Fixed focal point [m]

% Generate aperture

aperture = xdc_linear_array (128, lambda/2, element_height, kerf, 1, 1,focus);

% Set the impulse response and excitation of the emit aperture

impulse_response=sin(2*pi*f0*(0:1/fs:2/f0));

impulse_response=impulse_response.*hanning(max(size(impulse_response)))';

xdc_impulse (aperture, impulse_response);

excitation=sin(2*pi*f0*(0:1/fs:8/f0));

xdc_excitation (aperture, excitation);

% Set the seed of the random number generator

randn('seed',sum(100*clock))

% Initialize the ranges for the scatterers,血管里面的物质

% Notice that the coordinates are in meters

x_range=0.015; % x range for the scatterers [m]

y_range=0.015; % y range for the scatterers [m]

z_range=0.015; % z range for the scatterers [m]

z_offset=0.70; % Offset of the mid-point of the scatterers [m]

R=0.005; % Radius of blood vessel [m]

% Set the number of scatterers. It should be roughly

% 10 scatterers per resolution cell

c=1540; % Ultrasound propagation velocity [m/s]

f0=3e6; % Center frequency of transducer [Hz]

lambda=c/f0;

N=round(10*x_range/(5*lambda)*y_range/(5*lambda)*z_range/(lambda*2));

disp([num2str(N),' Scatterers'])

% Generate the coordinates and amplitude

% Coordinates are rectangular within the range.

% The amplitude has a Gaussian distribution.

x=x_range*(rand(1,N)-0.5);

y=y_range*(rand(1,N)-0.5);

z=z_range*(rand(1,N)-0.5);

% Find which scatterers that lie within the blood vessel

r=(y.^2+z.^2).^0.5;

within_vessel= (r < R)';

% Assign an amplitude and a velocity for each scatterer

v0=0.5; % Largest velocity of scatterers [m/s]

velocity=v0*(1-(r/R).^2).*within_vessel';

blood_to_stationary= 0.1; % Ratio between amplitude of blood to stationary tissue

amp=randn(N,1).*((1-within_vessel) + within_vessel*blood_to_stationary);

% Calculate a suitable Tprf

theta=45/180*pi;

f_max=2*v0*cos(theta)/c*f0;

fprf=3*f_max;

Tprf=1/fprf; % Time between pulse emissions [s]

Nshoots=128; % Number of shoots

% Find the response by calling field

for i=1:Nshoots

i

% Generate the rotated and offset block of sample

xnew=x*cos(theta)+z*sin(theta);

znew=z*cos(theta)-x*sin(theta) + z_offset;

scatterers=[xnew; y; znew;]' ;

% Calculate the received response

[v, t1]=calc_scat(aperture, aperture, scatterers, amp);

% Store the result

image_data(1:max(size(v)),i)=v;

times(i) = t1;

% Propagate the scatterers and alias them

% to lie within the correct range

x=x + velocity*Tprf;

outside_range= (x > x_range/2);

x=x - x_range*outside_range;

end

% Here the display of the data

% Here the display of the data is inserted

plot(image_data)

阅读    收藏 
标签:

volume

rendering

shear-warp

三维成像

分类: 算法

Volume Rendering


常见的三维成像有表面绘制和体绘制,surface rendering, volume rendering,后者需要庞大的计算量,为了利用硬件加速计算的的优势,我只关注volume rendering。

 

主要包括以下方法:

( 1 ) 基于图像空间扫描的绘制, 如光线投射( Ray Casting ) 算法;该方法是对射入观察者眼睛的所有光线,沿着光线路径对所有体元按照颜色和不透明度积分得到最后射出的颜色。Ray tracing:逆向跟踪射入的光线,遇到交点时类似积分。

( 2 ) 基于物体空间扫描的绘制, 如足迹表法( 又叫是splatting算法) 、 错切变形( Shear-Warp ) 算法、 体元投射( Cell Projection ) 法等。

 

Shear-Warp原理


其中Shear-Warp算法把三维投影变为三维数据场错切shear和二维图像变形warp两步实现,是目前最快的Volume Rendering算法。

我们来看看斯坦福大学Philippe Lacroute和 Marc Levoy的论文Fast Volume Rendering Using a Shear-Warp Factorization of the Viewing Transformation,Shear-Warp算法分为三个步骤:

  1. 物体空间->错切图像空间。如图一,横线为一个个slice,就是三维物体的二维切片,从上看就是线。Viewing rays是平行投影光线。经过shear变换后,在图像空间,切片和光线垂直。对于透视的情况,如图二,切片还要收缩。

http://s9/middle/679f93564bab577d54e98&amp;690

http://s3/middle/679f93564bab577dc4602&amp;690

  1. 按照从前往后的顺序组合切片。得到错切图像空间的二维中间图像。
  2. 通过Warp,把中间图像变形为最终投影图像。

     

Shear-Warp详解


Shear-Warp相当于对原坐标系做了变换,变换矩阵为:

http://s11/middle/679f93564bab577e41dea&amp;690

P说明以那个方向为主轴来切片,有xyz三种可能。S从物体空间变到错切空间。M(warp)再变回图像空间。以z为主轴时,平行投影S有

http://s15/middle/679f93562f4b16b0aeb3e&amp;690

透视投影S有,

http://s1/middle/679f93564bab5781e5860&amp;690

其中切片z0被拉伸了http://s5/middle/679f93564bab5781ddd04&amp;690。矩阵元素从M(view)得到。

最后,

http://s16/middle/679f93564bab57821840f&amp;690

图3为前述三个步骤详解。

  1. 沿着扫描线变换并重采样,甚至拉伸。
  2. 把切片的对应扫描线投影并叠加,alpha处理透明度。
  3. 根据M(warp)变换,需要再次重采样。

http://s2/middle/679f93564bab5782e6001&amp;690

Shear-warp算法


对于平行投影,首先对于原数据游程编码RLE(run-length encode),

  1. 1. 根据透明度阈值在体素(物体的像素别称)数据结构中作记录,跳过透明的体素,在rendering之前进行,对于三种矩阵P形式,及三种切片方式都要计算。2. 对于中间图像,在像素数据结构中保存此不透明像素到可透光像素位移,在rendering同时进行。最后只处理不完全透明和可视的体素。

http://s1/middle/679f93564bab57830b870&amp;690

  1. 开始重采样和组合。采用双线性插值滤波器(bilinear interp),每两个相邻扫描线计算得到一个中间图像扫描线。背光用聚合卷积,正面光用散射卷积。用查找表的方法实现透明度处理。

    http://s5/middle/679f93560791225a31624&amp;690

    http://s1/middle/679f93564bab5786da080&amp;690

  2. 再次用双线性滤波器把大的中间图像变为最终小图像。(general-purpose affine image warper with a bilinear filter)

这篇文章还提出了一种alpha传递函数,通过递归的办法实现透明度可变时的行程编码。先得到一个立方体八个顶点确定的八叉树,查表计算立方体是否透明,不透明则继续递归计算更小立方体,直到体积小到一定值。

http://s12/middle/679f93564bab578794fdb&amp;690

阅读    收藏 
  
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有