由于新App需要分享到各大网站,所以用了ShareKit这个开源库。为了广大中文用户,所以要对菜单名称等进行本地化语言处理一下。新版本的ShareKit自带了Localize的string文件,本以为可以直接使用,结果无论是模拟器还是真机测试,中文信息都无效…
查了好久完全不知道怎么回事
解决方法很简单
删掉自带的Localizable.strings文件,然后重新自己一一建立,立刻就解决
具体原因不解,但是删掉自己重来很管用
由于新App需要分享到各大网站,所以用了ShareKit这个开源库。为了广大中文用户,所以要对菜单名称等进行本地化语言处理一下。新版本的ShareKit自带了Localize的string文件,本以为可以直接使用,结果无论是模拟器还是真机测试,中文信息都无效…
查了好久完全不知道怎么回事
解决方法很简单
删掉自带的Localizable.strings文件,然后重新自己一一建立,立刻就解决
具体原因不解,但是删掉自己重来很管用
在Cocos2D中截图有2种方法
需要对CCDirector进行Category扩展,加入以下两个文件
CCDirector+ImageSave.h
#import <Foundation/Foundation.h> #import "cocos2d.h" @interface CCDirector (ImageSave) - (UIImage *)screenShotUIImage; - (CCTexture2D *)screenShotTexture2D; @end
CCDirector+ImageSave.m
#import "CCDirector+ImageSave.h"
@implementation CCDirector (ImageSave)
- (UIImage*) screenShotUIImage {
CGSize size = [self displaySizeInPixels];
//Create un buffer for pixels
GLuint bufferLenght=size.width*size.height*4;
GLubyte *buffer = (GLubyte *) malloc(bufferLenght);
//Read Pixels from OpenGL
glReadPixels(0,0,size.width,size.height,GL_RGBA,GL_UNSIGNED_BYTE,buffer);
//Make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLenght, NULL);
//Configure image
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * size.width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef iref = CGImageCreate(size.width,size.height,bitsPerComponent,bitsPerPixel,bytesPerRow,colorSpaceRef,bitmapInfo,provider,NULL,NO,renderingIntent);
uint32_t *pixels = (uint32_t *)malloc(bufferLenght);
CGContextRef context = CGBitmapContextCreate(pixels, [self winSize].width, [self winSize].height, 8, [self winSize].width*4, CGImageGetColorSpace(iref), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextTranslateCTM(context,0, size.height);
CGContextScaleCTM(context, 1.0, -1.0);
switch ([self deviceOrientation]) {
case CCDeviceOrientationPortrait:
break;
case CCDeviceOrientationPortraitUpsideDown:
CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(180));
CGContextTranslateCTM(context,-size.width, -size.height);
break;
case CCDeviceOrientationLandscapeLeft:
CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(-90));
CGContextTranslateCTM(context,-size.height, 0);
break;
case CCDeviceOrientationLandscapeRight:
CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(90));
CGContextTranslateCTM(context,size.width*0.5, -size.height);
break;
}
CGContextDrawImage(context, CGRectMake(0.0, 0.0, size.width, size.height), iref);
UIImage *outputImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];
//Dealloc
CGDataProviderRelease(provider);
CGImageRelease(iref);
CGContextRelease(context);
free(buffer);
free(pixels);
return outputImage;
}
- (CCTexture2D*) screenShotTexture2D {
return [[CCTexture2D alloc] initWithImage:[self screenShotUIImage]];
}
@end
使用的时候,如下就可以保存图片
#import "CCDirector+ImageSave.h" /* ... ... */ UIImage *screenshot = [[CCDirector sharedDirector] screenShotUIImage]; NSString *savePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Screenshot.png"]; [UIImagePNGRepresentation(screenshot) writeToFile:savePath atomically:YES];
CCRenderTexture是Cocos2D定义的类,所以直接使用吧
// 设定截图大小 CCRenderTexture *target = [CCRenderTexture renderTextureWithWidth:320 height:480]; [target begin]; // 添加需要截取的CCNode [someNode visit]; [target end]; NSString *savePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Screenshot.png"]; [target saveBuffer:savePath format:kCCImageFormatPNG];
其实iMac自带了Apple Magic Mouse,如果你电脑使用频率低,要大概凑合也不是不可以,但是由于iMac 27寸的分辨率高达2560*1440,magic mouse在没有外加软件调节仅靠系统设置的情况下,移动之慢简直令人发指。此外,MM的外形过于扁平,握着鼠标的时候手掌心会悬空,长期使用会使得手指酸痛。吹嘘的触控操作,其实尝鲜完之后会觉得也不过尔耳。总之,这个鼠标除了好看,基本没太多亮点。技术宅者为了健康,还是自重。
网上也有不少人推荐 罗技V470,一是蓝牙,可以不用多加一个接收器,二有白色款,配色跟iMac蛮搭的,本人不幸买了一个,iMac 21寸或者Macbook Air之流可能分辨率小,用起来还算顺畅,我自己的iMac 27,设置快速移动之后隐隐感觉移动掉帧,怎么甩都不舒畅,外加造型略微鼓起且非完全对称(适合右手鼠标),对于我这个左撇子的人来说,其实也不是很满意(右手凑合吧,但是没其他的手感好),重量适中,最大的问题其实就是掉帧了。
所以我最后被迫用回 罗技M215,要插入一个小小的USB接口的Nano接收器,手感还不错,价格异常便宜,我当初花80大洋左右入手,只是颜色不搭,外貌协会的童鞋考虑买个黑色的吧,至少不会像我蓝色的这么突兀。
如果你有更多的米买外设,果断买高端键鼠套装去吧。我当初纠结于一定要蓝牙的鼠标,这样可以省下一个USB接口,其实真没必要,iMac虽然只有4个USB,但是基本不会一次用满吧。要找一套蓝牙键鼠,选择非常少,现在大多都是2.5Ghz无线技术。果然不要蓝牙,其实就不会像我这么被坑了。
其实分页查询我第一反映是用SQLite的查询语句来操作,后来想想Core Data底层也是调用SQLite,应该也是可以分页查询的
不过iPhone开发毕竟中文资料不多,翻了下官方英文文档,找到下面的方法,主要使用下面两个函数
// 限定查询结果的数量 setFetchLimit // 查询的偏移量 setFetchOffset
最近正在熟悉各种API,没太多时间,直接上代码,其实蛮简单的
NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"RSSEntryModel" inManagedObjectContext:_managedObjectContext]; [request setEntity:entity]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"articleDate" ascending:NO]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; [request setSortDescriptors:sortDescriptors]; [request setFetchLimit:21]; [request setFetchOffset:_currentPage * 21]; NSArray *rssTemp = [_managedObjectContext executeFetchRequest:request error:&error];
这里贴上一个教程http://www.raywenderlich.com/934/core-data-tutorial-getting-started,3个篇幅说得更加仔细
他blog里的教程都很棒,我基本都看了遍
最近很不务正业的迷上了霹雳布袋戏,对于这种闽南语对白的剧集,的确有着先天的好感。想来多半是因为闽南语才是自己真正的母语,虽然不中用的自己其实有很多字词都不会说,而且感觉闽南语的延续也有些断层。一些书面语的字词,我这一辈的人多半是只能用普通话代劳,难以像外公那样,可以对着文章一字一音的朗读。
小时候对布袋戏并不热衷,即使在什么都好奇的年纪,木偶对我的杀伤力也远不如多啦A梦的口袋。以前就知道霹雳布袋戏剧情长的惊人,前几天搜了一下,立刻惊讶无言,从1984年至今,几十年未曾完结,这都已经可以比肩那些超长肥皂剧了。然而这么几十年来所有剧集所有角色的配音,居然都出自同一人——黄文择(霹雳孔雀令不是),实在是不得不服。就算你也和我一样一开始听着觉得鼻音很别扭,但是这样恐怖的实力,就算偶尔我听出熟悉的声音,我还是心服口服。
说起来大家说的霹雳布袋戏,指的是以素还真为主线,也就是《霹雳金光》开始的剧集,但是里面一些人物与黄俊雄时代的史艳文为主的《云州大儒侠》有一定的牵连,且在《霹雳金光》之前还有几部也是以“霹雳”作为前缀命名的布袋戏,对于一些人物的首次出场及典故,会有更多的交代。
所以,有这么复杂的关系,想知道霹雳布袋戏的全部剧集顺序,可以看wikipedia
至于黄氏三代的布袋戏风云史,可以看百度百科
由于实在是受不了有些人上传视频加了那么明显的水印,虽然没有他们的共享,也下不到剧集,但是那么频繁骚扰的水印是在是妨碍看戏的心情,所以我就开始收集一些网上的在线播放列表,一来省心,二来方便大家共享。若你真是喜欢霹雳布袋戏,有机会请支持正版DVD。
| 编号 | 名称 | ( 集 ) 数 | 时间 | 播放地址 |
|---|---|---|---|---|
| 01 | 云州大儒侠 | 583 | 1970年 | 由电视直接播出 |
| 02 | 史艳文 | 不详 | 1975年 | 由电视直接播出 |
| 03 | 苦海女神龙 | 不详 | 1976年 | 由电视直接播出 |
| 04 | 忠勇小金刚 | 不详 | 1977年 | 由电视直接播出 |
| 05 | 七彩霹雳门 | 不详 | 1978年 | 由电视直接播出 |
| 06 | 霹雳震灵霄 | 不详 | 1979年 | 由电视直接播出 |
| 07 | 霹雳真象 | 不详 | 1980年 | 由电视直接播出 |
| 08 | 霹雳万象 | 不详 | 1981年 | 由电视直接播出 |
| 09 | 霹雳天网 | 不详 | 1982年 | 由电视直接播出 |
| 10 | 霹雳侠踪 | 不详 | 1983年 | 由电视直接播出 |
| 11 | 霹雳城 | 8 | 1984年 | 优酷 |
| 12 | 霹雳神兵 | 8 | 1985年 | 优酷(缺第1集) |
| 13 | 霹雳金榜 | 8 | 1986年 | 优酷 |
| 14 | 霹雳震九宵 | 8 | 1987年 | 优酷 |
| 15 | 霹雳战将 | 8 | 1988年 | 优酷 |
| 16 | 霹雳金光 | 16 | 1988年06月 | 优酷 |
| 17 | 霹雳眼 | 20 | 1989年06月 | 优酷 |
| 18 | 霹雳至尊 | 15 | 1989年11月 | 优酷 |
| 19 | 霹雳孔雀令 | 10 | 1989年11月 | 优酷 |
| 20 | 霹雳剑魂 | 20 | 1990年01月 | 优酷 |
| 21 | 霹雳异数 | 40 | 1990年02月 | 皆是发行录像带 |
| 22 | 霹雳劫 | 30 | 1990年03月 | 皆是发行录像带 |
| 23 | 霹雳天阙 | 30 | 1990年06月 | 皆是发行录像带 |
| 24 | 霹雳紫脉线 | 20 | 1992年05月 | 皆是发行录像带 |
| 25 | 霹雳烽云 | 20 | 1993年04月 | 皆是发行录像带 |
| 26 | 霹雳天命 | 14 | 1993年11月 | 皆是发行录像带 |
| 27 | 霹雳狂刀 | 60 | 1993年12月 | 皆是发行录像带 |
| 28 | 霹雳王朝 | 30 | 1995年03月 | 皆是发行录像带 |
| 29 | 霹雳幽灵箭Ⅰ | 25 | 1995年09月 | 皆是发行录像带 |
| 30 | 霹雳外传之叶小钗传奇 | 6 | 1996年02月 | 皆是发行录像带 |
| 31 | 霹雳幽灵箭Ⅱ | 20 | 1996年03月 | 皆是发行录像带 |
| 32 | 霹雳英雄榜 | 50 | 1996年07月 | 皆是发行录像带 |
| 33 | 霹雳烽火录 | 30 | 1997年03月 | 皆是发行录像带 |
| 34 | 霹雳风暴 | 40 | 1997年07月 | 皆是发行录像带 |
| 35 | 霹雳狂刀之创世狂人 | 50 | 1998年04月 | 皆是发行录像带 |
| 36 | 霹雳雷霆 | 30 | 1999年02月 | 发行一集一片VCD |
| 37 | 霹雳英雄榜之江湖血路 | 40 | 1999年07月 | 发行一集一片VCD |
| 38 | 霹雳英雄榜之风起云涌Ⅰ | 20 | 2000年03月 | 发行一集一片VCD |
| 39 | 霹雳英雄榜之风起云涌Ⅱ | 30 | 2000年07月 | 发行一集一片VCD |
| 40 | 霹雳英雄榜之争王记 | 30 | 2001年01月 | 发行一集一片VCD |
| 41 | 霹雳图腾 | 20 | 2001年05月 | 发行一集一片DVD |
| 42 | 霹雳异数之龙图霸业 | 40 | 2001年08月 | 发行一集一片DVD |
| 43 | 霹雳封灵岛 | 20 | 2002年04月 | 发行一集一片DVD |
| 44 | 霹雳兵燹 | 48 | 2002年07月 | 发行一集一片DVD |
| 45 | 霹雳刀锋 | 30 | 2003年01月 | 发行一集一片DVD |
| 46 | 霹雳异数之万里征途 | 32 | 2003年06月27日 | 发行一集一片DVD |
| 47 | 霹雳九皇座 | 50 | 2003年10月17日 | 发行一集一片DVD |
| 48 | 霹雳劫之阇城血印 | 26 | 2004年04月09日 | 发行一集一片DVD |
| 49 | 霹雳劫之末世录 | 24 | 2004年07月09日 | 发行一集一片DVD |
| 50 | 霹雳皇朝之龙城圣影 | 40 | 2004年10月01日 | 发行一集一片DVD |
| 51 | 霹雳剑踪 | 30 | 2005年02月18日 | 发行一集一片DVD |
| 52 | 霹雳兵燹之刀戟戡魔录Ⅰ | 30 | 2005年06月03日 | 发行一集一片DVD |
| 53 | 霹雳兵燹之刀戟戡魔录Ⅱ | 40 | 2005年09月16日 | 发行两集一片DVD |
| 54 | 霹雳奇象 | 40 | 2006年02月03日 | 发行两集一片DVD |
| 55 | 霹雳谜城 | 40 | 2006年06月23日 | 发行两集一片DVD |
| 56 | 霹雳皇龙纪 | 50 | 2006年11月10日 | 发行两集一片DVD |
| 57 | 霹雳皇朝之铡䶮史 | 30 | 2007年05月04日 | 发行两集一片DVD |
| 58 | 霹雳开疆纪 | 40 | 2007年08月17日 | 发行两集一片DVD |
| 59 | 霹雳神州 | 30 | 2008年01月04日 | 发行两集一片DVD |
| 60 | 霹雳神州Ⅱ之苍玄泣 | 46 | 2008年04月18日 | 发行两集一片DVD |
| 61 | 霹雳神州Ⅲ之天罪 | 48 | 2008年09月26日 | 发行两集一片DVD |
| 62 | 霹雳天启 | 48 | 2009年03月13日 | 发行两集一片DVD |
| 63 | 霹雳震寰宇之刀龙传说 | 40 | 2009年09月12日 | 全家便利商店发行 |
| 64 | 霹雳震寰宇之龙战八荒 | 40 | 2010年01月29日 | 全家便利商店发行 |
| 65 | 霹雳震寰宇之兵甲龙痕 | 40 | 2010年06月18日 | 全家便利商店发行 |
| 66 | 霹雳经武纪之枭皇论战 | 40 | 2010年11月12日 | 全家便利商店发行 |
我们平时在WoW中按ESC键,从弹出的游戏菜单中选择“界面”,然后切换到“插件”标签,左边的列表可以看到一些插件名称,点击某一插件,可以在右边进行一些相应设置。
不过其实很多插件的功能设置会依靠聊天对话框输入命令来开启,或者在小地图上有个图标让你点,甚至干脆就没选项(比如我教程中写的那个),所以并不是所有插件都会添加到那个界面列表中。不过今天有人来问说,如何把自己编写的插件添加到这个菜单中去呢?
这里直接给出相关函数的说明链接
InterfaceOptions_AddCategory(panel)
http://wowprogramming.com/docs/api/InterfaceOptions_AddCategory
panel是frame类型,必须包含一个string类型name成员,也就是说,你至少要给这个frame定个名字,这样调用这个函数就可以添加自己插件的设置页面到列表中,并显示得出来。
老规矩,为了照顾新手,小写了一个只实现添加插件名字到列表中的代码,把代码下载解压扔到wow的插件目录下,进入游戏在界面中选择这个插件之后,右边只有一个按钮,随便按……没有任何功能。我还小加了段编写自定义命令的部分,输入/optiontest就可以直接开启设置页面。
如果有人想问说,怎么自定义命令呢,有3个步骤
代码如下
SLASH_OPTIONTEST1 = "/optiontest";--添加自定义命令名称 SlashCmdList["OPTIONTEST"] = OptionTest_SlashCommand;--函数名其实随意 local function OptionTest_SlashCommand(msg, editbox) --开启设置页面 InterfaceOptionsFrame_OpenToCategory(OptionTest.name); end
需要特别注意的SLASH_OPTIONTEST1跟SlashCmdList["OPTIONTEST"],你插件的名字在这里一定要大写(其他的插件也都这样写),我无从查起为何要这样,但是我试过改成小写均无效,谁来告诉我为嘛啊……
InterfaceOptionsFrame_OpenToCategory是开启我们前面提到的那个设置页面的函数,可以在WowProgramming查询详细资料。
还记得上一篇关于OpenCV移植到FPGA上的文章里,我只写了BMP图片的读写,关于如何显示,因为毕设没有需要,我也没有深入去弄。
后来几次有网友发邮件过来询问,很无奈自己也未曾尝试,更何况做毕设实验的板也早已经还给学校,这个部分就一直搁浅着。直到前一段lanying兄的来信,这个事情才有新的进展。
有个可能比较好的方案是使用GTK那些成熟的库然后整合上OpenCV来实现,这里只介绍一个初级的,也是lanying兄验证完的一个方法,就是使用FrameBuffer来显示图片
首先引用下别人的一点基础介绍
FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。
Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出 FrameBuffer这个设备来供用户态进程实现直接写屏。Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过 Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接 进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由 Framebuffer设备驱动来完成的。
但是呢,FrameBuffer同时也有很大的限制,比如分辨率这些在系统设置里面如果设定完了,就不能实时更改了,同理包括显示的颜色深度。相关方面的东西请自行了解,这里只给个小链接让大家看看:http://www.91linux.com/html/article/kernel/20071204/8805.html
然后就像上次提到的图片读取的编写,要读取什么格式的图片,你自己必须对那种格式的编码存储结构很了解,然后才在那基础上继续进行。因为FrameBuffer的显示图片的思路是,自己读取图片文件的像素信息,然后按照每一行每一列逐一将像素点的信息写入到FrameBuffer对应的内存空间上。
这次只说个实现思路,具体的技术细节因未亲身验证所以不妄加解说,只是与lanying兄信件往来不时了解下,下面给出一个例程给大家参考,由于没有板验证,所以诸位看代码的时候如果有小细节错误,还望见谅。
http://blog.tyreal.net/download/FrameBuffer
若你有更好的方案,请来信tyreal.han@gmail.com赐教,不胜感激
距离我上一次写东西,俨然已经过去了4个月。一毕业,工作之后,就处于盲目奔波状态,却没什么新的收获。在一个南方还算有点名气的集团里弄嵌入式开发,待了一个月多久就离职了,所做的事情无非只是预备热身,没太多值得道来。
此刻的我,又回到了复习考研的路上。只有3个月的时间里,跟其他正常的统考计算机的人一样要复习3科,外加一本没有学过的离散数学。这样的成功概率有多小,其实根本就不在意,这只是年少轻狂的血液躁动之后的不安分。考研究竟有没有意义,根本不去深究,只是选自己曾经想走的路。
昨天跟Jennal聊天的时候,审视了下自己,除了只会写点小玩意,从来没弄过中等规模以上的开发。做过最拿得上台面的东西,也就只有那份毕设了,虽然可能是在FPGA上第一份OpenCV移植成功的资料,也经常有人来信问我一些事情,不过平心而论,我也只是做完毕设之后就没再深入了。对于OpenCV,其实我并不是很懂,算法这种东西对我这个电子系出身又不是很勤快研究的人来说,更是门外汉的水平。偶然间收到一个英国研究生的来信,对于3D高斯模糊优化这种问题只好汗颜回信说我并不了解。而后关于OpenCV移植的一些来信,都只是简单的说一些建议跟指导,每次都谨慎回复,深怕误导了别人。前些日子看到Jennal写的漫画下载器,还是蛮羡慕的,因为自己从来就没弄个像样的项目出来,答应帮他做的QuesLite的Flex界面也拖到最后只能道歉说没时间动手。
就是这样长期处于羡慕别人的状态,无论是写程序,还是弹吉他。读一个都已经底层到物理级别的微电子专业,编程是自学的,弹吉他也只是有了好友的吉他之后,在网上搜了下乐理看看视频自娱自乐而已。当初折腾了半天才写出了WoW的插件,看弹奏视频也是揣摩了好久才把切音练熟。每每看到很多弹唱自如的视频旁边写着“新手”二字,我都只能保持⊙﹏⊙!的表情。反正我天生节奏无能,又没有音感,唱歌的时候已经是满负载运作了,又弹又唱现在还是办不到的。至于技术,硬件方面皮毛都不懂,软件能力疲软,自己这样的单核CPU脑袋却曾经狂妄的想要并行处理,这又是多么讽刺的事情。
工作之后才意识到自己一些想法的改变,会不会以后就不会再有为自己曾经的想法而活的冲动呢?自认为辛辛苦苦才从同辈们手中抢来的工作,一个月的工资是2500,在厦门这样的地方要涨到猴年马月才能出头呢?一直认为,在分配不均的局势下,想法比努力重要,不过,这或许又是为自己的不努力找借口。什么叫“辛辛苦苦”,我这种大三之后才知道“努力”的人根本没资格谈这个词。
大三的暑假,跑去厦大找阿睿跟飞龙学东西,那段蹭吃蹭喝的日子里,晚饭后散步在环岛路走回海韵校区的路上,记得有几次跟阿睿的对话都让他对我这个偏执的小孩颇为无奈。我跟Jennal说我辞职准备考研,他很自然的认为我会报考厦大。那些在木栈道上来来回回的每一晚,舒适的海风还有那缓缓拂拭沙滩的浪涛,都未曾让自己放下焦虑的心情,那个暑假的一切,都只是为了挽回某人的盲目努力而已。然而,后来几次再回到厦大西村的时候,自己也没再试着一路走回海韵,却偶尔遐想,有朝一日若能平静地再次回到那条路上,从晚上的上弦场旁漫步而过,云淡风轻,仿佛是自我救赎的结局一样。
过后的日子,曾经每天倒数不断准备的金山面试,已无任何意义。再之后的日子,如同当初在木栈道上错乱的心情一样,背离自己内心深处的答案越来越远。此刻,只想将这一切错乱,亲手停摆。
在这还有热血去燃烧的岁月里,真庆幸曾经的梦想,一直都在。
自己本科毕设的内容涉及到OpenCV
所以需要移植OpenCV到Nios平台上的嵌入式系统中
可是自己搜遍所有可能的资料
还是没有看到有人做过
即使在我毕设答辩前5天
自己依旧没有做成功
几度犹豫
曾想过腰斩题目改变毕设内容
最后忍住坚持了下来
论文末尾还都写上了移植失败分析
之后的几天
事情就像喜剧结局一样的峰回路转
原本以为不成功的移植居然在小组答辩演示的时候成功了
然后在大组答辩之前找出了不稳定的原因
于是
这篇文章就有了雏形
导师曾让我整理好自己毕设论文中的关于OpenCV的移植研究的部分
可以考虑发表出去
毕竟没人做过还是有些参考价值
自己这一段一是休息外加忙着聚会
二是不知道这样的技术含量值不值得发表
自知现在浮躁的环境发表个论文就像在刷个人数据
其实不见得文章都有什么价值
自己在查阅资料的时候也曾见过几篇文章的测试数据跟精度居然都能一模一样
只是换到自己要发表的时候
就诸多考虑
终究不想敷衍了事
只是想保持自己心中学术思想之正直
听起来多少有点自视清高的酸味
酸就酸吧
得瑟归得瑟,终究对得起自己
唠叨这么久终于开始要说正题了
感谢诸位忍到此刻的耐心
由于之前没人做过这方面的移植研究
所以本文能参考的资料不多
限于笔者的水平
若有错误之处还望见谅
对于第一步,给个自己写的文章当参考——《uClinux在Nios II平台上的移植》,我将从第二步开始说起
值得注意的是:
本文使用nios2-gcc-3.4.6 + OpenCV 1.1 pre测试,OpenCV的1.0、2.0版本我也尝试过编译,均告失败,只有1.1测试通过。
你可以从http://sourceforge.net/projects/opencvlibrary/files/这里下载OpenCV的源码
点击View all files那个按钮,然后下载opencv-unix 1.1pre1,在终端输入
tar -zxvf opencv-1.1pre1.tar.gz
解压供后面使用
如果你还尝试了别的版本并且也成功了,请不吝告诉在下
进入刚才解压出来的源码文件夹,输入配置命令
$ ./configure --host=nios2-linux --without-gtk --without-carbon --without-quicktime --without-1394libs --without-ffmpeg --without-python --without-swig --enable-static --disable-shared --disable-apps CXX=nios2-linux-g++ --prefix=/home/lee/uccv
–host 指定要编译的目标平台
–witout-* 禁用各种函数库,一是uClinux本来就不支持这里的大部分库,除了gtk,其他的其实你不填也是一样不会编译进去;二是出于精简的需要,说不定日后真支持某个库了,这些我们不需要的东西还是明令去除的好
–enable-static –disable-shared 启动静态链接库,禁用动态链接,因为嵌入式系统对内核的大小要求很看重,不适合将OpenCV库编译成动态链接库,因为这样生成的库都是完整且较为庞大,所以在移植程序数量较少的情况下,通过静态链接库,只将程序用到的部分与程序编译链接到一起,是相对比较理想的选择。另外一个原因是我曾经想使用动态链接库来运行,可是编译出错,暂时无解。
–disable-apps 禁止编译范例程序,因为要编译可以在FPGA上的uClinux系统运行的OpenCV程序,需要在编译的时候额外添加参数,而且我们等会还要自行测试编译,这里一定得禁用掉,否则会导致之后make出错。
CXX 指定编译器。其实这个可以不加,只要host里面指定的平台系统能识别,最后生成的makefile里面的编译器配置信息都是一样的,之所以还保留是因为之前参考ARM下的移植文章,在此留着给大家之后编译若有错误当做一个切入点。
–prefix 可以设置OpenCV编译结果想要安装的路径,这里设置为笔者Fedora中用户所在的个人文件夹。
然后经过一堆输出信息刷新,你可以看到如下信息:
v4l那是因为我毕设要做双目测距程序,需要用到摄像头,所以我留着(不过最后还是失败了,西奈……uClinux下摄像头驱动的移植又是个头痛的问题)。
一切正常的话,我们就开始编译
$ make
如果make没有出错,就开始安装目标平台上的OpenCV函数库吧
$ make install
然后在我们设置的路径下找到lib文件夹,进入就可以看到编译好的静态链接库了
由于不能再用Highgui库了,如果你的程序有用到Highgui,我们就得自己重写文件读写以及图片显示函数,这里着重讲下如何对图片文件读取以及之后如何使用自己读取的图片数据来初始化IplImage,以此为例,其他部分按照这样的思路同样去修改。
为了对原来写好的程序进行最低程度的修改,我们只删除Highgui的头文件引用,然后自行添加个头文件与源文件,在其中加入的图片读取函数的名称,跟原来一样为IplImage* cvLoadImage(char* filename, int iscolor = 1)
在自行编写cvLoadImage()函数中,根据要读取的图片格式不同,对应自己编写读取算法,唯一相同的步骤是,最后将图片数据读取到一个BYTE指针指向的空间
读取好图片,可以使用OpenCV的cxcore中的两个函数来初始化IplImage
IplImage* cvLoadImage(char* fileName, int iscolor = 1)
{
/*...省略其他代码...*/
//创建IplImage变量的信息头
IplImage* img = cvCreateImageHeader(cvSize(width,height), depth, channel);
//利用BYTE指针数据初始化IplImage
cvSetData(img, (void *)blocks, lineByte);
/*...省略其他代码...*/
return img;
}
width、height是要创建IplImage图像的宽度与高度
depth是图像的位深
channel是图像的通道数
blocks是读取来的图像数据的BYTE*指针
lineByte是OpenCV中图像每一行的数据宽度,OpenCV规定图像的每一行数据宽度都必须是4的倍数,但是图像不同位数、不同宽度,不一定满足这个条件,所以这个变量之前需要额外进行一个简单的计算处理
lineByte = (width * biBitCount/8)/4*4; //biBitCount是图像一个像素占用的位宽大小
以上width、height、biBitCount等int变量的值都可以从图片的文件头读取得知,具体方法请查阅不同图片格式的资料说明。
需要说清楚,我们只是自己简单的写了一个读取特定图片格式的函数,比不上原来的highgui原来的API那么好用,各种格式都支持,不过一般应用的时候,格式都比较固定,这点相对不是什么大问题。
delete[] img->imageDataOrigin; cvReleaseImageHeader(&img);
至此,我们就完成了脱离Highgui自行完成图片文件读取函数,至于文件写入乃至图片显示,限于篇幅原因就不详细讲解,基本思想掌握,剩下的就是自由发挥了。
等我工作定下之后,闲暇再找机会补写看看。
这里留下一个自己写的BMP读取的源码,供大家参考下,写的很搓很随意,而且只读取彩色图像,随意瞥下了解就好。
<—传送门—>
弄到这里,有了OpenCV的静态函数库,也有脱离Highgui的源码,就可以开始编译链接目标平台的程序了
#先编译文件读取程序 $ nios2-linux-g++ -c bmpDecoder.cpp bmpDecoder.o -I/home/lee/uccv/include/opencv #再编译测试OpenCV程序 $ nios2-linux-g++ -c test.cpp test.o -I/home/lee/uccv/include/opencv #最后与函数库链接在一起 $ nios2-linux-g++ -o test bmpDecoder.o test.o -L/home/lee/uccv/lib -lcv -lcvaux -lcxcore -lml -lpthread -elf2flt
-I 指定源码中的头文件引用库位置
-L 指定静态链接函数库位置
-lcv -lcvaux -lcxcore -lml 是需要链接的OpenCV的几个静态链接库,顺序很重要,更改顺序很可能导致undefined reference,需要根据自己编写的程序微调这个参数列表的顺序。
-lpthread 支持多线程程序,我是根据错误提示信息加上这个参数,更深入的理由我并未深究。
-elf2flt 编译为flt格式程序,uClinux默认没有MMU,只支持绝对内存地址的二进制格式,这个记得一定要加上
假如没有什么意外的话,你就会获得最后编译出来的目标平台的OpenCV程序文件
编译好了,链接成功了,按照我之前给的那篇文章的说明,再烧写下载程序到目标板上测试运行。
虽然我觉得以Cyclone II级别的FPGA器件运行OpenCV的效率,还不能到实际应用的程度,不过以现在FPGA的发展势头,多尝试新的SoPC应用开发,待硬件资源足够之时,也未必不是一大优势。
至于一些目前其他高端的FPGA的运行表现,由于自己没有条件测试,在此就不妄加评价了。
最近上网点击链接后,地址栏老重定向,出现一堆类似
http://59.59.58.22/req.php?str1=112774803450039633&t=00312613659330290855001277480345&str2=http://www.ccb.cn/portal/cn/home/
的地址,网页也因此刷不出来
稍微查了一下,据说是万恶的电信的DNS劫持想推广告导致的
根据大家的提示,我也把DNS更改了google的免费DNS服务器
8.8.8.8
8.8.4.4
结果还是个悲剧……
最后查到有个人提示说,要清除本机的dns缓存
在windows的控制台终端输入
C:\>ipconfig /flushdns
最后再上网浏览网页,终于可以不用老是被电信恶心了
——————————————————————————————
最近发现,这样的方法还是解决不掉
除了打电话去投诉估计还真没办法了