Chinaunix首页 | 论坛 | 博客
  • 博客访问: 356885
  • 博文数量: 132
  • 博客积分: 3066
  • 博客等级: 中校
  • 技术积分: 781
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-14 16:19
文章分类

全部博文(132)

文章存档

2012年(1)

2010年(50)

2009年(81)

我的朋友

分类: C/C++

2009-06-04 10:32:17

源程序如下,其中函数IsContourP用来判断某点是不是边界点。
BOOL Contour(HWND hWnd)
{
 DWORD                 OffBits,BufSize;
    LPBITMAPINFOHEADER  lpImgData;
 LPSTR                   lpPtr;
 HLOCAL                 hTempImgData;
 LPBITMAPINFOHEADER   lpTempImgData;
 LPSTR                   lpTempPtr;
 HDC                     hDc;
 HFILE                   hf;
 LONG                   x,y;
 POINT                   StartP,CurP;
 BOOL                    found;
 int                       i;
 int                  direct[8][2]={{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},
{-1,1},{0,1},{1,1}};

//我们处理的实际上是256级灰度图,不过只用到了0和255两种颜色。
 if( NumColors!=256){
     MessageBox(hWnd,"Must be a mono bitmap with grayscale palette!","Error Message",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;
}
//到位图数据的偏移值
 OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);
 //缓冲区大小
 BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);
//为新图缓冲区分配内存
 if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL)
    {
     MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|
MB_ICONEXCLAMATION);
        return FALSE;
    }
    lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);   
 lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);
 //新图缓冲区初始化为255
 memset(lpTempImgData,(BYTE)255,BufSize);
 //拷贝头信息
 memcpy(lpTempImgData,lpImgData,OffBits);
 //找到标志置为假
 found=FALSE;
 for (y=0;y  lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes);
  for (x=0;x   if (*(lpPtr++) ==0) found="TRUE"; //找到了最左上的黑点,一定是个边界点
 }
 if(found){ //如果找到了,才做处理
//从上面的循环退出时,x,y坐标都做了加1的操作。在这里把它们减1,得到起
//始点坐标StartP
  StartP.x=x-1;
  StartP.y=y-1;
  lpTempPtr=(char *)lpTempImgData+(BufSize-
LineBytes-StartP.y*LineBytes)+StartP.x;
  *lpTempPtr=(unsigned char)0; //起始点涂黑
  //右邻点
     CurP.x=StartP.x+1;
  CurP.y=StartP.y;
  lpPtr=(char *)lpImgData+(BufSize-LineBytes-CurP.y*LineBytes)+CurP.x;
  if(*lpPtr!=0){ //若右邻点为白,则找右下邻点
      CurP.x=StartP.x+1;
   CurP.y=StartP.y+1;
   lpPtr=(char *)lpImgData+(BufSize-LineBytes-CurP.y*LineBytes)+CurP.x;
   if(*lpPtr!=0){ //若仍为白,则找下邻点
       CurP.x=StartP.x;
    CurP.y=StartP.y+1;
   }
  else{ //若仍为白,则找左下邻点
       CurP.x=StartP.x-1;
    CurP.y=StartP.y+1;
   }
  }
  while (! ( (CurP.x==StartP.x) &&(CurP.y==StartP.y))){
//知道找到起始点,循环才结束
   lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes
-CurP.y*LineBytes)+CurP.x;
   *lpTempPtr=(unsigned char)0;
   for(i=0;i<8;i++){
//按右,右上,上,左上,左,左下,下,右下的顺序找相邻点
//direct[i]中存放的是该方向x,y的偏移值
    x=CurP.x+direct[i][0];
    y=CurP.y+direct[i][1];
  //lpPtr指向原图数据,lpTempPtr指向新图数据
    lpTempPtr=(char *)lpTempImgData
+(BufSize-LineBytes-y*LineBytes)+x;
    lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes)+x;
    if( ( (*lpPtr==0)&&(*lpTempPtr!=0) ) ||
( (x==StartP.x) &&(y==StartP.y)))
    //原图中为黑点,且新图中为白点(表示还没搜索过)时才处理
    //另一种可能是找到了起始点
     if(IsContourP(x,y,lpPtr)){ //若是个边界点
      //记住当前点的位置
         CurP.x=x;
      CurP.y=y;
      break;
     }
   }
  }
 }
    if(hBitmap!=NULL)
     DeleteObject(hBitmap);
 hDc=GetDC(hWnd);
 //创立一个新的位图
 hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpTempImgData,
  (LONG)CBM_INIT,(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +
  NumColors*sizeof(RGBQUAD),(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS);
 hf=_lcreat("c:\\contour.bmp",0);
 _lwrite(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));
 _lwrite(hf,(LPSTR)lpTempImgData,BufSize);
 _lclose(hf);
 //释放内存和资源
  ReleaseDC(hWnd,hDc);
 LocalUnlock(hTempImgData);
 LocalFree(hTempImgData);
 GlobalUnlock(hImgData);
 return TRUE;
}
//判断某点是不是边界点,参数x,y 为该点的坐标,lpPtr为指向原位图数据的指针
BOOL IsContourP(LONG x,LONG y, char *lpPtr)
{
 int     num,n,w,e,s;
 n=(unsigned char)*(lpPtr+LineBytes); //上邻点
 w=(unsigned char)*(lpPtr-1); //左邻点
 e=(unsigned char)*(lpPtr+1); //右邻点
 s=(unsigned char)*(lpPtr-LineBytes); //下邻点
 num=n+w+e+s;
 if(num==0) //全是黑点,说明是个内部点而不是边界点
  return FALSE;
 return TRUE;
}

系统分类: 资源共享
用户分类: 编程技术
标签: 无标签
来源: 转贴
发表评论 阅读全文(453) | 回复(0)

1

关于投票
个人收藏的编程下载资源全部公布

java方面的:
it人资讯交流网

这个网站是我最近才发现的,虽然内容不多,但是提供的相关java工具挺齐全。还有就是里面提供了java教学视频录象的免费下载,好像一两周更换一段。个人觉得挺适合初学者的,尤其是那个classpath的设置,讲的很透彻,大家有空可以看一看。

java官方站点(英文)

要想了解最新的java动态,下载最新的java相关,比如j2se、j2ee、j2se的最新jdk版本就来这里吧。

java中文站

这个可能大家都知道,不用说了,他提供的java资源是最丰富的。注册论坛是免费的,还送积分,用积分可以下载软件和电子书等,如果积分用完了,就需要自己发表一些文章来赚新的积分。

中文java网站

跟上面站点类似的一个站,宗旨就是:为java爱好者服务。值得一看!

锋网

综合性的java网站,内含“下载中心”、“教程教学”等栏目。

java动力

网站的内容可以,但是最为出色的是它所运用的flash技术,我就不在这里多说了,大家去看看就知道了,一个字“酷”!!!

vc方面的:
vc知识库

这个网站就不用多说了,学习vc必去之地。网站专门提供了免费的ftp下载,好东东巨多!

vc之路

综合软件开发网站,以vc为主。“资源中心”有许多值得下载的东东。

visual c++/mfc开发指南

以讲述windows开发为主的站点,提供了最新的源代码,开发工具,开发资料,开发教程和对好的开发站点,开发工具,图书做介绍,同时为从事开发的朋友提供发布自己开发的软件,代码和工具场所。

c维视点

最近发现的vc好站,书籍、软件、代码下载一应具全!!!


游戏开发:
风云工作室
~cloudwu/2000/index.html

标点游戏制作


未来开发者
http://www.fdev.net/


综合的:
中国软件网

中国最大的开发者网络,他之所以著名就是因为他的论坛,大家有空可以去看看,能下到很多不错的东东,另外也是交流学习的好地方。

电子书籍的:


最后公布一个巨好的,狂多的电子书下载

还有巨好的

biplip移动开发网论坛

雷神的WINCE页面

eMbedded Programming

华人wince论坛

美斯比论坛

移动技术网社区

嵌入式研究网

eMbedded Visual C++论坛 CN Dev Forum
http://www.copathway.com/cndevforum/cndevforum.asp
新闻组
(EN)
新闻组
(EN)ICP=embedded&sLCID=US&newsgroup=microsoft.public.windowsce.embedded.vc(EN)
Pocket PC Developer Network
(EN)
(EN)
CE Programming
(EN)
(EN)
windows embedded tech bulletin
(EN)

开源网站介绍
开源网站,和编程技术网站不同的是提供和作者直接交流和源代码管理平台(subversion或cvs)
,最全的开源网站,支持所有语言,许多经典项目,如电驴,BT,python(语言解释器),7zip,phpMyAdmin,FileZilla,WinSCP等等都是在上面发展壮大的
,都是和apache有关并受apache基金支持的开源项目,如httpd,lucene,项目语言也很杂
,主要是C++语言项目,subversion是在它上面开源的,另外还有一些编程辅助工具的开源项目
此外还有一些特定语言的开源网站,如
,ruby开源项目
,vc++开源项目

itepub.com的电子书绝对经典

系统分类: 资源共享
用户分类: 编程技术
标签: 无标签
来源: 转贴
发表评论 阅读全文(465) | 回复(0)

1

关于投票
VC++6.0实现视频数据实时获取的探讨
文章标题:VC++6.0实现视频数据实时获取的探讨
原 作 者:谭佐军 吴鹏飞
原 出 处:vczx.com
发 布 者:谭佐军
发布类型:原创
发布日期:2006-09-05
今日/总浏览:2/4776

  摘要VC++6.0中利用VFW技术实现视频数据实时获取的过程中,针对回调函数的处理中所碰到的问题、图像采集中原始数据的获取以及捕获窗口的建立的问题进行了详细的讨论,并给出了具体的解决办法。

  关键词 VFW 图像采集 回调函数

  引言

  以光学为基础,融光电子学、计算机技术、激光技术、图像处理技术等现代科学技术为一体的图像测量技术在测量领域中形成了新的测量技术,基于数字图像处理技术的图像测量系统目前已广泛应用于几何量的测量、航空等遥感测量、精密复杂零件的微尺寸测量和外观测量,以及光波干涉图、应力应变场状态分布等和图像有关的技术领域中。在基于数字图像处理技术的图像测量系统中,必须解决的问题就是图像采集,即图像数据的获取,采集的图像数据用于后期的图像处理。

  视频图像捕获一般来讲有两种方法,一种是利用视频捕获卡所附带的SDK开发工具,这种捕获方法的实现是与设备有关的,依赖于视频捕获卡与摄像头的类型,不利于灵活应用;另外一种捕获方法是Microsoft的Visual C++自从4.0版就开始支持Video for Windows(简称VFW),这给视频捕获编程带来了很大的方便,利用VFW技术的可以提高视频捕获的灵活性,减少了对视频设备的依赖。在VC++6.0中,含有MCIAVI、DRAWDIB、AVIFILE和AVICAP等组件。通过它们之间的协调工作,可以完成播放、编辑、文件管理和视频捕获等功能,为视频图像处理和分析带来非常大的便利,本文就利用VFW进行视频数据的实时采集中的碰到的几个实际问题进行探讨。

   VFW库函数简介

  视频数据的实时采集主要是通过调用AVICap32.dll创建AVICap窗口类 ,由AVICap窗口类中的消息、宏函数、结构以及回调函数来完成。 AVICap在捕获视频方面具有明显的优势,它能直接访问视频缓冲区,不需要生成中间文件,实时性很高,它也可将数字视频保存到事先建好的文件中。实际应用表明,通过这种方法,提高了视频采集的效果和程序运行的效率,同时也减少了对硬件的依赖性,提高了程序的兼容性和移植性。

  VFW的视频采集功能主要包括捕获视频流至AVI文件(capCaptureSequence)、捕获视频流至缓存(capCaptureSequenceNofile)、捕获视频流至AVI文件(capCaptureSingleFrame)、本地预览(capPreview/capOverlay)和捕获单帧预览(capGrabFrame/capGrabFrameNoStop)等。VFW还提供了回调函数 ,允许应用程序精确控制视频流的捕获、检测错误、监控状态变化 ,以及在捕获两帧数据的空隙和每捕获新帧时对实时数据进行处理。

  几个实际问题的探讨

  1、回调函数处理的问题

  回调函数是至今为止最有用的编程机制之一。在Windows中,回调函数更是窗口过程、钩子过程、异步过程调用所必需的,在整个回调过程中自始至终地使用回调方法。人们可以注册回调方法以获得加载/卸载通知,未处理异常通知,数据库/窗口状态修改通知,文件系统修改通知,菜单项选择,完成的异步操作通知,过滤一组条目等等。在VFW中有几条这样的宏函数,如用于设置在发生某事件后能作出反应的回调函数的宏函数,它和中断服务机制很相似,条件一满足,程序会自动进入相应的回调函数体中,该函数究竟要做些什么,全由开发者借助其参数自行编制程序来确定。利用VFW获取实时视频数据通常可以运用视频处理的回调机制(call-backmechanism) 获得实时数据缓冲区的首址和长度并对图像数据进行处理,同时也可以进行视频数据的直接传输,在这一方面很多文章都作了具体的介绍。但是按照大多数文章的介绍,在具体的应用过程中,对回调函数作如下定义时,程序总是无法通过编译:

{
 LRESULT CALLBACK FrameCallbackProc(HWND ghWnd,LPVIDEOHDR lpVData)
 unsigned char *data;
 data=lpVData->lpData;//获得视频数据首地址,并将数据存入data数组中以便处理
}

  通过研究,发现根本原因是回调函数是基于C编程的Windows SDK的技术,不是针对C++的,可以将一个C函数直接作为回调函数,但是如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。其错误是普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递一个指向自身的指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为什么C++类的多个实例可以共享成员函数但是确有不同的数据成员。由于this指针的作用,使得将一个CALLBACK型的成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数安装失败。要解决这一问题的关键就是不让this指针起作用,通过采用以下两种典型技术可以解决在C++中使用回调函数所遇到的问题。这种方法具有通用性,适合于任何C++。

  (1) 不使用成员函数,直接使用普通C函数,为了实现在C函数中可以访问类的成员变量,可以使用友元操作符(friend),在C++中将该C函数说明为类的友元即可。这种处理机制与普通的C编程中使用回调函数一样。

  (2) 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,如果作不到这一点将不具有实际意义。解决的办法也很简单,就是使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如pThis=this,然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函数了。这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情况,可以使用回调函数的一个参数来传递this指针,从而实现数据成员共享。这种方法稍稍麻烦,这里就不再赘述。

  因此,可以对回调函数作如下定义:
static LRESULT CALLBACK FrameCallbackProc(HWND ghWnd,LPVIDEOHDR lpVData)
{
 unsigned char *data;
 data=lpVData->lpData;//获得视频数据首地址,并将数据存入data数组中以便处理
}
  2、图像采集中的问题

  视频数据的采集是整个应用的关键,根据应用的不同可以将视频帧采集到的文件或采集的缓存直接加以处理。利用VFW获取实时视频数据通常可以运用视频处理的回调机制(call-backmechanism) 获得实时数据缓冲区的首址和长度并对图像数据进行实时处理,但是在这个过程中图像处理程序不能太长,否则视频显示不流畅。另外,在实际采集过程中,有些图像采集卡程序对通过回调机制所获取的数据进行了压缩,比如DC10,而在图像测量系统高精度的要求,压缩后的图像数据直接影响以后的图像处理工作。通过采用以下两种典型技术可以实现将没有压缩的视频帧的图像数据的采集。

  (1) 通过研究发现,尽管图像采集卡驱动程序对通过回调机制所获取的数据进行了压缩,但是利用VFW中的capEditCopy( )宏函数将帧图像缓冲区中的图像数据拷贝到剪贴板上时,并没有压缩图像数据,因此可以不采用回调机制而直接利用capGrabFrameNoStop()捕获一帧图像,然后将数据拷贝拷贝到剪贴板上,再通过DIB(Device Independent Bitmap)操作获取内存中图像数据首地址,进行后续的图像数据处理。具体的代码片段如下:
//获得capEditCopy( )拷贝到剪贴板中的图像数据句柄,通过CF_DIB参数指定数据
HANDLE hData;
::GlobalFree ((HGLOBAL)hData);
hData=(HANDLE)CopyHandle(::GetCliPBoardData(CF_DIB));

  (2) 利用capFileSaveDIB将缓冲区中的图像数据转化为DIB位图直接保存为文件,需要处理时,再读取位图中的图像数据到内存进行后续的处理。这种方式因为有一个文件存储和读取的延迟,对于实时的图像处理来说,响应速度比前者要稍慢,经过多次实验证明,只要图像处理算法的计算量不是很大,仍然可以保证比较好的实时性。

  3、图像采集窗口建立的问题
 
  在视频捕获之前需要创建一个捕获窗,所有的捕获操作及其设置都以它为基础。一个AVICap视窗口句柄描述了声频与视频流的细节,这样就使程序员的应用程序从AVI文件格式,声频视频缓冲管理,低层声频视频驱动访问等解脱出来。AVICap即是预定义的Windows窗口类,利用该窗口类创建的子窗口可以与视频采集设备的驱动程序相联系,该子窗口的客户区用来显示采集设备捕获的实时视频图像。

  但是在实际应用过程中,应用程序可能会基于单文档(SDI)、多文档或者是基于对话框的界面,由于三种类型的不同,捕获窗的具体创建应根据具体要求而有所区别。不管是采用哪种类型,根据实时视频的显示的具体要求,关键是如何获取捕获窗口的父窗口句柄。通常捕获窗口的创建可以如下两种方式:

  (1)获取动态创建的父窗口的句柄,动态的创建捕获窗口。具体的代码片段如下:

CFrameWnd m_wndSource;
if(!m_wndSource.CreateEx(WS_EX_TOPMOST,NULL,"source",WS_CAPTION,CRect(100,100,150,180),NULL,0))
return -1;
m_wndSource.ShowWindow(SW_HIDE);
m_WndCap=capCreateCaptureWindow((LPSTR)" 视频捕捉测试程

  (2)获取显示的实时视频窗口的句柄,静态的创建捕获窗口。具体的代码片段如下:
m_hCapWnd = capCreateCaptureWindow((LPSTR)TEXT("视频捕捉测试程序"),WS_CHILD|WS_VISIBLE,
0,0,768,576,this->m_hWnd,0);

 

  结束语

  利用VFW技术实现视频数据实时获取,提高了视频采集的效果和程序运行的效率,同时也减少了对硬件的依赖性,提高了程序的兼容性和移植性。在很多基于数字图像处理技术的图像测量系统中都使用了这种方法。本文就具体应用中所碰到的实际问题进行了详细的讨论,并给出了具体的解决办法。

系统分类: 软件开发
用户分类: 编程技术
标签: 无标签
来源: 转贴
发表评论 阅读全文(463) | 回复(0)

1

关于投票
YUY2视频转化RGB格式
//YUY2视频转化RGB格式 by hardy 2007-10-17
//
inline void YUY2_RGB(BYTE *YUY2buff,BYTE *RGBbuff,DWORD dwSize)
{

 //B = 1.164(Y - 16)         + 2.018(U - 128)
 //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
 //R = 1.164(Y - 16) + 1.596(V - 128)
 BYTE *orgRGBbuff = RGBbuff;
 for(DWORD count="0";count {
  //Y0 U0 Y1 V0
  float Y0 = *YUY2buff;
  float U = *(++YUY2buff);
  float Y1 = *(++YUY2buff);
  float V = *(++YUY2buff);
  ++YUY2buff;

  *(RGBbuff) =   (BYTE)(Y0 + (1.370705 * (V-128)));          
  *(++RGBbuff) = (BYTE)(Y0 - (0.698001 * (V-128)) - (0.337633 * (U-128)));  
  *(++RGBbuff) = (BYTE)(Y0 + (1.732446 * (U-128)));        

  *(++RGBbuff) = (BYTE)(Y1 + (1.370705 * (V-128)));          
  *(++RGBbuff) = (BYTE)(Y1 - (0.698001 * (V-128)) - (0.337633 * (U-128)));  
  *(++RGBbuff) = (BYTE)(Y1 + (1.732446 * (U-128)));        
  ++RGBbuff;
 }
}
inline void YUY2_RGB2(BYTE *YUY2buff,BYTE *RGBbuff,DWORD dwSize)
{

//R = Y + 1.14V
//G = Y - 0.39U - 0.58V
//B = Y + 2.03U

// R = Y + 1.403V'
//G = Y - 0.344U' - 0.714V'
//B = Y + 1.770U'
 BYTE *orgRGBbuff = RGBbuff;
 for(DWORD count="0";count {
  //Y0 U0 Y1 V0
  float Y0 = *YUY2buff;
  float U = *(++YUY2buff);
  float Y1 = *(++YUY2buff);
  float V = *(++YUY2buff);
  ++YUY2buff;

  float R,G,B;
  
  R = (Y0 + 1.14f*V);
  G=(Y0 - 0.39f*U-0.58f*V);  
  B=(Y0 +2.03f*U);
  if(R<0) R =0;
  if(R>255) R="255";
  if(G<0) G =0;
  if(G>255) G="255";
  if(B<0) B =0;
  if(B>255) B="255";

  *(RGBbuff) =     (BYTE)B;         
  *(++RGBbuff) =  (BYTE)G;
  *(++RGBbuff) =  (BYTE)R;

  R = (Y1 + 1.14f*V);
  G=(Y1 - 0.39f*U-0.58f*V);  
  B=(Y1 +2.03f*U)   ;
  if(R<0) R =0;
  if(R>255) R="255";
  if(G<0) G =0;
  if(G>255) G="255";
  if(B<0) B =0;
  if(B>255) B="255";

  *(++RGBbuff) =     (BYTE)B;         
  *(++RGBbuff) =  (BYTE)G;
  *(++RGBbuff) =  (BYTE)R;
  ++RGBbuff;
 }
}

inline void YUY2_RGB4(BYTE *YUY2buff,BYTE *RGBbuff,DWORD dwSize)
{


// R = Y + 1.403V'
//G = Y - 0.344U' - 0.714V'
//B = Y + 1.770U'
 BYTE *orgRGBbuff = RGBbuff;
 for(DWORD count="0";count {
  //Y0 U0 Y1 V0
  float Y0 = *YUY2buff;
  float U = *(++YUY2buff);
  float Y1 = *(++YUY2buff);
  float V = *(++YUY2buff);
  ++YUY2buff;

  float R,G,B;
  
  R = (Y0 + 1.403f*V);
  G=(Y0 - 0.344f*U-0.714f*V);  
  B=(Y0 +1.77f*U);
  if(R<0) R =0;
  if(R>255) R="255";
  if(G<0) G =0;
  if(G>255) G="255";
  if(B<0) B =0;
  if(B>255) B="255";

  *(RGBbuff) =     (BYTE)R;         
  *(++RGBbuff) =  (BYTE)G;
  *(++RGBbuff) =  (BYTE)B;
  R = (Y1 + 1.403f*V);
  G=(Y1 - 0.344f*U-0.714f*V);  
  B=(Y1 +1.77f*U);
  if(R<0) R =0;
  if(R>255) R="255";
  if(G<0) G =0;
  if(G>255) G="255";
  if(B<0) B =0;
  if(B>255) B="255";

  *(++RGBbuff) =     (BYTE)R;         
  *(++RGBbuff) =  (BYTE)G;
  *(++RGBbuff) =  (BYTE)B;
  ++RGBbuff;
 }
}

inline void YUY2_RGB3(BYTE *YUY2buff,BYTE *RGBbuff,DWORD dwSize)
{

 //B = 1.164(Y - 16)         + 2.018(U - 128)
 //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
 //R = 1.164(Y - 16) + 1.596(V - 128)
 BYTE *orgRGBbuff = RGBbuff;
 for(DWORD count="0";count {
  //Y0 U0 Y1 V0
  float Y0 = *YUY2buff;
  float U = *(++YUY2buff);
  float Y1 = *(++YUY2buff);
  float V = *(++YUY2buff);
  ++YUY2buff;

  *(RGBbuff) =   (BYTE)(1.164f*(Y0 - 16)+ 2.018f*(U - 128));          
  *(++RGBbuff) = (BYTE)(1.164f*(Y0 - 16) - 0.813f*(V - 128) - 0.391f*(U - 128));  
  *(++RGBbuff) = (BYTE)(1.164f*(Y0 - 16) + 1.596f*(V - 128));        

  *(++RGBbuff) =   (BYTE)(1.164f*(Y0 - 16)+ 2.018f*(U - 128));          
  *(++RGBbuff) = (BYTE)(1.164f*(Y0 - 16) - 0.813f*(V - 128) - 0.391f*(U - 128));  
  *(++RGBbuff) = (BYTE)(1.164f*(Y0 - 16) + 1.596f*(V - 128));         
  ++RGBbuff;
  
 }
}
//
void VC4000Graber::YUY2_RGB(BYTE *YUY2buff,BYTE *RGBbuff,DWORD dwSize)
{
//
//C = Y - 16
//D = U - 128
//E = V - 128
//R = clip(( 298 * C           + 409 * E + 128) >> 8)
//G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
//B = clip(( 298 * C + 516 * D           + 128) >> 8)
 BYTE *orgRGBbuff = RGBbuff;
 for(DWORD count="0";count {
  //Y0 U0 Y1 V0
  BYTE Y0 = *YUY2buff;
  BYTE U = *(++YUY2buff);
  BYTE Y1 = *(++YUY2buff);
  BYTE V = *(++YUY2buff);
  ++YUY2buff;

  LONG Y,C,D,E;
  BYTE R,G,B;
  
  Y = Y0;
  C = Y-16;
  D = U-128;
  E = V-128;
  R = clip255(( 298 * C           + 409 * E + 128) >> 8);
  G = clip255(( 298 * C - 100 * D - 208 * E + 128) >> 8);
  B = clip255(( 298 * C + 516 * D           + 128) >> 8);

  *(RGBbuff) =   B;          
  *(++RGBbuff) = G;  
  *(++RGBbuff) = R;        

  Y = Y1;
  C = Y-16;
  D = U-128;
  E = V-128;
  R = clip255(( 298 * C           + 409 * E + 128) >> 8);
  G = clip255(( 298 * C - 100 * D - 208 * E + 128) >> 8);
  B = clip255(( 298 * C + 516 * D           + 128) >> 8);
  *(++RGBbuff) =   B;          
  *(++RGBbuff) = G;  
  *(++RGBbuff) = R;        
  ++RGBbuff;
  
 }
}

BYTE VC4000Graber::clip255(LONG v)
{
 if(v<0) v="0";
 else if(v>255) v="255";
 return (BYTE)v;
}

系统分类: 软件开发
用户分类: 编程技术
标签: 无标签
来源: 转贴
发表评论 阅读全文(960) | 回复(0)

1

关于投票
pid源代码
 

#ifndef  __PID__H
#define  __PID__H


#pragma code
#ifdef DEBUG_PID
#define SEND_PID_STRING(STRING) send_string((STRING))
#define SEND_PID_UCHAR_HEXA(CHR) send_unsigned_char_as_hexa((CHR))
#define SEND_PID_INT(INT) send_int_as_hexa((INT))
#define SEND_PID_LONG_HEXA(LNG) send_long_as_hexa((LNG))
#define SEND_PID_BYTE(CHR) send_byte((CHR))
static char string_state[]="State: ";
static char string_control[]="CTRL_Term: ";
static char string_error_term[]="Err Term: ";
static unsigned short counter = 0;
static char new_line[]="\r\n";
static char string_int_term[]="Int Term: ";
static char string_pos_dif[]="Pos Dif: ";
static char string_des_vel[]="Des. Veloc:"; ?    static char string_des_ask[]="Ask. Veloc:";
static char string_ask_acc[]="Ask. Accel:";
static char string_des_pos[]="Des. Pos:";
static char string_int_term_of[]="Int.Term. OverFlow!";
static char string_control_overflow[]="Cont.Term Overflow!";
static char string_control_term[]="Ctrl. Term:";
static char string_pwm[]="PWM: ";
#else
#define SEND_PID_STRING(STRING) 1
#define SEND_PID_UCHAR_HEXA(CHR) 1
#define SEND_PID_INT(INT) 1
#define SEND_PID_LONG_HEXA(LNG) 1
#define SEND_PID_BYTE(CHR) 1
#endif


#pragma udata
unsigned char traj_finished;



// Buffer to copy the current mesured position
signed long mesured_position_buf[2];



#pragma code
/********************************************************/
/*          Timer stuff                                 */
/********************************************************/



void init_timer (void)
{
   timerH[0]=timerH[1]=0;
   time_ptr = (unsigned char *)&time;
   INTCONbits.TMR0IE = 1;
   // Inlined, we need to change TMR0H before TMR0L (see datasheet)
   TMR0H = 0;
   TMR0L = 0;
   T0CON = 0x07;// 16 bit timer, 1:256 prescaler, not started
INTCON2bits.TMR0IP =1; //TMR0 High Priority
}


void start_timer (void)
{
  T0CONbits.TMR0ON = 1;
}


void stop_timer (void)
{
  T0CONbits.TMR0ON = 0;
  TMR0H = 0;
  TMR0L = 0;
  timerH[0]=timerH[1]=0;
}


//********************************************************
//          Sampling stuff                               *
//********************************************************


void get_time (void)
{
  // TODO do we need 32bits precision ?
   // In that case we need to enable the tmr0 overflow interrupt,
   // and increment a 16bits-wide counter in the interrupt routine.
   //

  *time_ptr = TMR0L;
  *(time_ptr + 1) = TMR0H;
  *(time_ptr + 2) = timerH[0];
  *(time_ptr + 3) = timerH[1];
 
}


void get_sample (void)
{
  // copy the mesured position to a buffer to calculate pid
  mesured_position_buf[0] = mesured_position[0];
  mesured_position_buf[1] = mesured_position[1];
}



void get_derivative_sample (void)
{


  old_derivative[0] = new_derivative[0];
  old_derivative[0] = new_derivative[0];


  new_derivative[0] = error_term[0];
  new_derivative[1] = error_term[1];


  derivative_term[0] = new_derivative[0] - old_derivative[0];
  derivative_term[1] = new_derivative[1] - old_derivative[1];


}


//*********************************************************
//*         Pid stuff                                     *
//*********************************************************
void desired_position_accel (void)
{
long temps = (time-time_offset[index]);
    desired_velocity[index] = asked_accel[index]*(temps >> 16);


    if(desired_velocity[index] >= (asked_velocity[index] >> 16)) {
       state[index] = STATE_CNST;
       desired_position[index] =  asked_velocity[index] * (temps >> 17);
       stop_distance[index] = desired_position[index];
       time_to_stop[index] = (time-time_offset[index]);
    }
    else
  desired_position[index] = desired_velocity[index] * (temps >> 1);
}


void desired_position_cnst (void)
{
long temps = (time-time_offset[index]);
    desired_position[index] = stop_distance[index] +
                              asked_velocity[index]*((temps - time_to_stop[index]) >> 16);
    if (desired_position[index] >= asked_position[index] - stop_distance[index] ) {
      time_to_stop[index] = temps;
      stop_distance[index] = desired_position[index];
      state[index] = STATE_DECEL;
    }
}


void desired_position_decel (void)
{
long temps = (time-time_offset[index]) - time_to_stop[index];
    desired_position[index] = stop_distance[index] + asked_velocity[index]*(temps >> 16)- asked_accel[index] * (temps >> 16) * (temps>> 1);
    if (desired_position[index] >= asked_position[index]) {
      desired_position[index] = asked_position[index];
      state[index] = STATE_STOP;
    }
}


void calculate_desired_position (void)
{
  switch (state[index]) {
    case STATE_ACCEL:
      desired_position_accel();
      break;
    case STATE_CNST:
      desired_position_cnst();
      break;
    case STATE_DECEL:
      desired_position_decel();   
      break;
    default:
      return;
  }
}


void calculate_error_term (void)
{
    position_difference = desired_position[index] - mesured_position_buf[index];
    error_term[index] = ( int ) position_difference ;
    // if position_difference not on 16 bits, satursate error_term...
    // TODO check that
    if (error_term[index] != position_difference)
      error_term[index] = (position_difference < 0) ? -0x7fff : 0x7fff;
   
integration_term_buffer = integration_term[index] + error_term[index];

integration_term[index] =  (short long)(integration_term_buffer);


if(integration_term[index] != integration_term_buffer){
  integration_term[index] = (integration_term_buffer < 0) ? -0x7fffff:0x7fffff ;
  //DEBUG
  //SEND_PID_STRING(string_int_term_of);
}



    // TODO The integration limit is not yet done
}


void do_pid (void)
{
   if (state[index] == STATE_STOP) {
      if (desired_position[index] >= mesured_position[index]) {
  control_terms[index]=0;
         return;
      }
    }
    control_term_buffer = coef_prop*error_term[index] + coef_deriv*(derivative_term[index]) + coef_integ*( (int) (integration_term[index] >> 8) );
control_terms[index] = (int)(control_term_buffer);


if(control_terms[index] != control_term_buffer){
  control_terms[index] = (control_term_buffer < 0)? -0x7fff : 0x7fff;
  //DEBUG
  //SEND_PID_STRING(string_control_overflow);
}


//*************************************************************
//           Update pwms                       *
//*************************************************************
// Called only once



void update_pwms(void)
{
  // TODO check signs
  if (control_terms[0]<0) {
    CCPR1L = ((-control_terms[0])>>7); // TODO is it only 7 ? signed -> unsigned...
    pwm_signs.sign0 = 0;
  }
  else {
    CCPR1L = (control_terms[0]>>7);
    pwm_signs.sign0 = 1;
  }


  if (control_terms[1]<0) {
    ECCPR1L = ((-control_terms[1])>>7); // TODO is it only 7 ? signed -> unsigned...
    pwm_signs.sign1 = 0;
  }
  else {
    ECCPR1L = (control_terms[1]>>7);
    pwm_signs.sign1 = 1;
  } 
}  
 


void pid_main_loop (void)
{
doMainLoop:
  while (!(start_motor[0]||start_motor[1]))
    Nop();
  status = STATUS_BUSY;
  sample_counter = 0;
  start_timer();


doSample:
  for (index = 0; index < 2; ++index) {
    if (start_motor[index]) {
      state[index] = STATE_ACCEL;
      get_time();
      time_offset[index] = time;
      signalRegister_LSB[index].traj_complete = 0;
      signalRegister_LSB[index].motor_off = 0;
    }
    start_motor[index] = 0;
  }
  get_time();
  sample_time=time+8; // next sample time. prescaler = 256 -> 8*256 = 2048
  get_sample();
  ++sample_counter;



  for (index = 0; index < 2; ++index) {
    calculate_desired_position();
    calculate_error_term();
  }


  if (sample_counter == derivative_sample) {
    sample_counter = 0;
    get_derivative_sample();
  }


  for (index = 0; index < 2; ++index) {
    do_pid();
  } 
  //update pwms : try to synchronise as much as possible
  update_pwms(); 
 
  traj_finished = 1;
  for (index = 0; index < 2; ++index) {
    if (state[index] == STATE_STOP && control_terms[index] == 0) {
      signalRegister_LSB[index].traj_complete = 1;
      signalRegister_LSB[index].motor_off = 1;
    }
    else traj_finished = 0;
  }


//DEBUG
  if (counter == 1) {
  counter = 0;
  //SEND_PID_STRING(string_control);
  //SEND_PID_INT(control_terms[0]);SEND_PID_BYTE('\t');
  //SEND_PID_INT(control_terms[1]);SEND_PID_STRING(new_line);
 
  SEND_PID_STRING(string_des_pos);
  SEND_PID_LONG_HEXA(desired_position[0]);SEND_PID_BYTE('\t');
  SEND_PID_LONG_HEXA(desired_position[1]);SEND_PID_STRING(new_line);


  SEND_PID_STRING(string_des_vel);
  SEND_PID_LONG_HEXA(desired_velocity[0]);SEND_PID_BYTE('\t');
  SEND_PID_LONG_HEXA(desired_velocity[1]);SEND_PID_STRING(new_line);


  SEND_PID_STRING(string_pwm);
  SEND_PID_UCHAR_HEXA(PWM0_DUTY_CYCLE);SEND_PID_BYTE('\t');
  SEND_PID_UCHAR_HEXA(PWM1_DUTY_CYCLE);SEND_PID_STRING(new_line);
 
  //SEND_PID_STRING(string_des_ask);
  //SEND_PID_LONG_HEXA((asked_velocity[0] >> 16));SEND_PID_BYTE('\t');
  //SEND_PID_LONG_HEXA((asked_velocity[1] >> 16));SEND_PID_STRING(new_line);


  //SEND_PID_STRING(string_int_term);
  //SEND_PID_LONG_HEXA(integration_term[0]);SEND_PID_BYTE('\t');
  //SEND_PID_LONG_HEXA(integration_term[1]);SEND_PID_STRING(new_line);

  //SEND_PID_STRING(string_control_term);
  //SEND_PID_LONG_HEXA(control_terms[0]);SEND_PID_BYTE('\t');
  //SEND_PID_LONG_HEXA(control_terms[1]);SEND_PID_STRING(new_line);


  //SEND_PID_STRING(string_ask_acc);
  //SEND_PID_LONG_HEXA(asked_accel[0]>>16);SEND_PID_BYTE('\t');
  //SEND_PID_LONG_HEXA(asked_accel[1]>>16);SEND_PID_STRING(new_line);


   //SEND_PID_STRING(string_pos_dif);
  //SEND_PID_LONG_HEXA(position_difference);
  //SEND_PID_STRING(new_line);


  //SEND_PID_STRING(string_error_term);
  //SEND_PID_INT(error_term[0]);SEND_PID_BYTE('\t');
  //SEND_PID_INT(error_term[1]);SEND_PID_STRING(new_line);


  //SEND_PID_STRING(string_int_term);
  //SEND_PID_LONG_HEXA(integration_term[0]);SEND_PID_BYTE('\t');
  //SEND_PID_LONG_HEXA(integration_term[1]);SEND_PID_STRING(new_line);

  SEND_PID_STRING(string_state); 
  SEND_PID_UCHAR_HEXA(state[0]);SEND_PID_BYTE('\t');
  SEND_PID_UCHAR_HEXA(state[1]);SEND_PID_STRING(new_line);SEND_PID_STRING(new_line);


}
counter++;


  if (!traj_finished) {
    while (time < sample_time){
       get_time();
}


    goto doSample;


  }
 
  status = STATUS_MOTOR_OFF | STATUS_TRAJECT_END;
  stop_timer();
  goto doMainLoop;
}



#endif  /*__PID__H*/

阅读(686) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~