C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图

C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图

C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图

+BIT祝威+悄悄在此留下版了个权的信息说:

最近需要用OpenGL绘制文字,这是个很费时费力的事。一般的思路就是解析TTF文件从而得到字形的贴图,然后通过OpenGL绘制贴图的方式显示文字。

本篇记录了解析TTF文件并把所有字形安排到一张大贴图上的过程。

使用FreeType

想从零开始解析TTF文件是一个比较大的工程,所以目前就借助FreeType。FreeType是一个开源的跨平台的TTF文件解析器。当然,它还支持解析OpenType等格式的文件。

+BIT祝威+悄悄在此留下版了个权的信息说:

预备工作

找一个TTF文件

你可以从C:\Windows\Fonts里找到很多TTF文件,我就不提供了。TTF文件里包含了文字的字形。比如下面这两个就是本篇开头的两张贴图展示的TTF:

下载FreeType源码

你可以在Github上搜索到FreeType项目,也可以到别的什么地方下载某个版本的FreeType。比如我下载的是2.6版。

源码下载解压后如上图所示。

下载CMake

我想用visual studio打开并编译它,但它没有sln工程文件。所以我们先要用CMake来自动生成一个freetype.sln文件。CMake你可以自行百度找到,由于博客园提供的空间有限,我这里也不保留CMake的安装包了。

安装完CMake后桌面上会有这样一个图标。这就是CMake。

 

+BIT祝威+悄悄在此留下版了个权的信息说:

创建FreeType.sln

有了CMake,就可以创建freetype.sln了。

打开CMake,按下图所示指定所需的参数,即可生成freetype.sln。

 

下面这一步指定Visual Studio。

 

看到"Generating Done"就说明成功了。

 

打开文件夹,可以看到出现了freetype.sln。

 

编译生成freetype.dll

有了freetype.sln,用visual studio打开,即可编译生成freetype.lib。但我们需要的是DLL,怎么办?按照下述步骤即可实现。

修改宏定义

找到ftoption.h文件,如下图所示,添加两个宏定义。

1 #define FT_EXPORT(x) __declspec(dllexport) x
2 #define FT_BASE(x) __declspec(dllexport) x

修改项目配置

如下图所示,在freetype属性页,把配置类型和目标文件扩展名改为.dll。

生成freetype.DLL

现在重新编译项目,就会生成freetype.dll了。

+BIT祝威+悄悄在此留下版了个权的信息说:

C#调用FreeType.dll

效果图

拿到了freetype.dll,下一步就是在C#里调用它。本篇期望用它得到的效果图已经贴到本文开头,这里再贴一下:

字形(Glyph)信息

英文单词Glyph的意思是"字形;图象字符;纵沟纹"。这就是字形。

一个字形有3个重要的信息:宽度、高度、基线高度。

如上图所示,从f到k,这是6个字形。

每个字形都用红色矩形围了起来。这些红色的矩形高度对每个字形都是相同的,只有宽度不同。

每个字形还用黄色矩形围了起来,这些黄矩形的宽度、高度就是字形的宽度、高度。

图中还有一个蓝色的矩形,它的上边沿与红色矩形是重合的(为了方便看,我没有画重合),它的下边沿就是"基线"。对于字母"g",它有一部分在基线上方,一部分在基线下方,在基线上方那部分的高度就称为"基线高度"。

所以,基线高度就是一个字形的黄色矩形框上边沿到蓝色矩形框下边沿的距离。有了这个基线高度,各个字形才能整齐地排列到贴图上。

如果没有基线高度的概念,你看的到贴图就会是这个样子:

与上面的效果图对比一下,你就知道它们的区别了。

封装freetype.dll

有了上面的基础,就可以开始干活了。首先要封装一些freetype相关的类型。这一步比较枯燥且冗长,我把核心类型放在这里,不想看直接跳过即可。

  1     public abstract class FreeTypeObjectBase<T> : IDisposable where T : class
  2     {
  3         /// <summary>
  4         /// 指针
  5         /// </summary>
  6         public IntPtr pointer;
  7 
  8         /// <summary>
  9         /// 对象
 10         /// </summary>
 11         public T obj;
 12 
 13         public override string ToString()
 14         {
 15             return string.Format("{0}: [{1}]", this.pointer, this.obj);
 16         }
 17 
 18         #region IDisposable Members
 19 
 20         /// <summary>
 21         /// Internal variable which checks if Dispose has already been called
 22         /// </summary>
 23         private Boolean disposed;
 24 
 25         /// <summary>
 26         /// Releases unmanaged and - optionally - managed resources
 27         /// </summary>
 28         /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
 29         private void Dispose(Boolean disposing)
 30         {
 31             if (disposed)
 32             {
 33                 return;
 34             }
 35 
 36             if (disposing)
 37             {
 38                 //TODO: Managed cleanup code here, while managed refs still valid
 39             }
 40             //TODO: Unmanaged cleanup code here
 41             ReleaseResource();
 42             this.pointer = IntPtr.Zero;
 43             this.obj = null;
 44 
 45             disposed = true;
 46         }
 47 
 48         /// <summary>
 49         /// Unmanaged cleanup code here
 50         /// </summary>
 51         protected abstract void ReleaseResource();
 52 
 53         /// <summary>
 54         /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 55         /// </summary>
 56         public void Dispose()
 57         {
 58             // Call the private Dispose(bool) helper and indicate 
 59             // that we are explicitly disposing
 60             this.Dispose(true);
 61 
 62             // Tell the garbage collector that the object doesn't require any
 63             // cleanup when collected since Dispose was called explicitly.
 64             GC.SuppressFinalize(this);
 65         }
 66 
 67         #endregion
 68 
 69     }
 70 
 71     /// <summary>
 72     /// FreeType库
 73     /// </summary>
 74     public class FreeTypeLibrary : FreeTypeObjectBase<FT_Library>
 75     {
 76         /// <summary>
 77         /// 初始化FreeType库
 78         /// </summary>
 79         public FreeTypeLibrary()
 80         {
 81             int ret = FreeTypeAPI.FT_Init_FreeType(out this.pointer);
 82             if (ret != 0) { throw new Exception("Could not init freetype library!"); }
 83 
 84             this.obj = (FT_Library)Marshal.PtrToStructure(this.pointer, typeof(FT_Library));
 85             //lib = Marshal.PtrToStructure<Library>(libptr);
 86         }
 87 
 88         protected override void ReleaseResource()
 89         {
 90             FreeTypeAPI.FT_Done_FreeType(this.pointer);
 91         }
 92 
 93     }
 94 
 95     /// <summary>
 96     /// 初始化字体库
 97     /// </summary>
 98     public class FreeTypeFace : FreeTypeObjectBase<FT_Face>
 99     {
100 
101         /// <summary>
102         /// 初始化字体库
103         /// </summary>
104         /// <param name="library"></param>
105         /// <param name="fontFullname"></param>
106         /// <param name="size"></param>
107         public FreeTypeFace(FreeTypeLibrary library, string fontFullname)//, int size)
108         {
109             int retb = FreeTypeAPI.FT_New_Face(library.pointer, fontFullname, 0, out pointer);
110             if (retb != 0) { throw new Exception("Could not open font"); }
111 
112             this.obj = (FT_Face)Marshal.PtrToStructure(pointer, typeof(FT_Face));
113 
114         }
115 
116         /// <summary>
117         /// Unmanaged cleanup code here
118         /// </summary>
119         protected override void ReleaseResource()
120         {
121             FreeTypeAPI.FT_Done_Face(this.pointer);
122         }
123 
124     }
125  
126     /// <summary>
127     /// 把字形转换为纹理
128     /// </summary>
129     public class FreeTypeBitmapGlyph : FreeTypeObjectBase<FT_BitmapGlyph>
130     {
131         /// <summary>
132         /// char 
133         /// </summary>
134         public char glyphChar;
135         public GlyphRec glyphRec;
136 
137         /// <summary>
138         /// 把字形转换为纹理    
139         /// </summary>
140         /// <param name="face"></param>
141         /// <param name="c"></param>
142         public FreeTypeBitmapGlyph(FreeTypeFace face, char c, int size)
143         {
144             // Freetype measures the font size in 1/64th of pixels for accuracy 
145             // so we need to request characters in size*64
146             // 设置字符大小?
147             FreeTypeAPI.FT_Set_Char_Size(face.pointer, size << 6, size << 6, 96, 96);
148 
149             // Provide a reasonably accurate estimate for expected pixel sizes
150             // when we later on create the bitmaps for the font
151             // 设置像素大小?
152             FreeTypeAPI.FT_Set_Pixel_Sizes(face.pointer, size, size);
153 
154             // We first convert the number index to a character index
155             // 根据字符获取其编号
156             int index = FreeTypeAPI.FT_Get_Char_Index(face.pointer, Convert.ToChar(c));
157 
158             // Here we load the actual glyph for the character
159             // 加载此字符的字形
160             int ret = FreeTypeAPI.FT_Load_Glyph(face.pointer, index, FT_LOAD_TYPES.FT_LOAD_DEFAULT);
161             if (ret != 0) { throw new Exception(string.Format("Could not load character '{0}'", Convert.ToChar(c))); }
162             
163             int retb = FreeTypeAPI.FT_Get_Glyph(face.obj.glyphrec, out this.pointer);
164             if (retb != 0) return;
165             glyphRec = (GlyphRec)Marshal.PtrToStructure(face.obj.glyphrec, typeof(GlyphRec));
166 
167             FreeTypeAPI.FT_Glyph_To_Bitmap(out this.pointer, FT_RENDER_MODES.FT_RENDER_MODE_NORMAL, 0, 1);
168             this.obj = (FT_BitmapGlyph)Marshal.PtrToStructure(this.pointer, typeof(FT_BitmapGlyph));
169         }
170 
171         protected override void ReleaseResource()
172         {
173             //throw new NotImplementedException();
174         }
175     }
封装freetype的核心类型

 

使用freetype时,首先要初始化库

1             // 初始化FreeType库:创建FreeType库指针
2             FreeTypeLibrary library = new FreeTypeLibrary();
3 
4             // 初始化字体库
5             FreeTypeFace face = new FreeTypeFace(library, this.fontFullname);

 

之后需要获取一个字形时,就

1                 char c = '&';
2                 int fontHeight = 48;
3                 FreeTypeBitmapGlyph glyph = new FreeTypeBitmapGlyph(face, c, fontHeight);

glyph里包含了字形的宽度、高度和用byte表示的灰度图。

字形集->贴图

得到glyph就可以生成整个贴图了,代码如下。

  1     /// <summary>
  2     /// 用一个纹理绘制ASCII表上所有可见字符(具有指定的高度和字体)
  3     /// </summary>
  4     public class ModernSingleTextureFont
  5     {
  6         private string fontFullname;
  7         private char firstChar;
  8         private char lastChar;
  9         private int maxWidth;
 10         private int fontHeight;
 11         private int textureWidth;
 12         private int textureHeight;
 13         Dictionary<char, CharacterInfo> charInfoDict = new Dictionary<char, CharacterInfo>();
 14 
 15         /// <summary>
 16         /// 用一个纹理绘制ASCII表上所有可见字符(具有指定的高度和字体)
 17         /// </summary>
 18         /// <param name="fontFullname"></param>
 19         /// <param name="fontHeight">此值越大,绘制文字的清晰度越高,但占用的纹理资源就越多。</param>
 20         /// <param name="firstChar"></param>
 21         /// <param name="lastChar"></param>
 22         /// <param name="maxWidth">生成的纹理的最大宽度。</param>
 23         public ModernSingleTextureFont(string fontFullname, int fontHeight, char firstChar, char lastChar, int maxWidth)
 24         {
 25             this.fontFullname = fontFullname;
 26             this.fontHeight = fontHeight;
 27             this.firstChar = firstChar;
 28             this.lastChar = lastChar;
 29             this.maxWidth = maxWidth;
 30         }
 31 
 32         public System.Drawing.Bitmap GetBitmap()
 33         {
 34             // 初始化FreeType库:创建FreeType库指针
 35             FreeTypeLibrary library = new FreeTypeLibrary();
 36 
 37             // 初始化字体库
 38             FreeTypeFace face = new FreeTypeFace(library, this.fontFullname);
 39 
 40             GetTextureBlueprint(face, this.fontHeight, this.maxWidth, out this.textureWidth, out this.textureHeight);
 41 
 42             System.Drawing.Bitmap bigBitmap = GetBigBitmap(face, this.maxWidth, this.textureWidth, this.textureHeight);
 43 
 44             face.Dispose();
 45             library.Dispose();
 46 
 47             return bigBitmap;
 48         }
 49 
 50         private System.Drawing.Bitmap GetBigBitmap(FreeTypeFace face, int maxTextureWidth, int widthOfTexture, int heightOfTexture)
 51         {
 52             System.Drawing.Bitmap bigBitmap = new System.Drawing.Bitmap(widthOfTexture, heightOfTexture);
 53             Graphics graphics = Graphics.FromImage(bigBitmap);
 54 
 55             //for (int i = (int)this.firstChar; i <= (int)this.lastChar; i++)
 56             for (char c = this.firstChar; c <= this.lastChar; c++)
 57             {
 58                 //char c = Convert.ToChar(i);
 59                 FreeTypeBitmapGlyph glyph = new FreeTypeBitmapGlyph(face, c, this.fontHeight);
 60                 bool zeroSize = (glyph.obj.bitmap.rows == 0 && glyph.obj.bitmap.width == 0);
 61                 bool zeroBuffer = glyph.obj.bitmap.buffer == IntPtr.Zero;
 62                 if (zeroSize && (!zeroBuffer)) { throw new Exception(); }
 63                 if ((!zeroSize) && zeroBuffer) { throw new Exception(); }
 64 
 65                 if (!zeroSize)
 66                 {
 67                     int size = glyph.obj.bitmap.width * glyph.obj.bitmap.rows;
 68                     byte[] byteBitmap = new byte[size];
 69                     Marshal.Copy(glyph.obj.bitmap.buffer, byteBitmap, 0, byteBitmap.Length);
 70                     CharacterInfo cInfo;
 71                     if (this.charInfoDict.TryGetValue(c, out cInfo))
 72                     {
 73                         if (cInfo.width > 0)
 74                         {
 75                             System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(cInfo.width, cInfo.height);
 76                             for (int tmpRow = 0; tmpRow < cInfo.height; ++tmpRow)
 77                             {
 78                                 for (int tmpWidth = 0; tmpWidth < cInfo.width; ++tmpWidth)
 79                                 {
 80                                     byte color = byteBitmap[tmpRow * cInfo.width + tmpWidth];
 81                                     bitmap.SetPixel(tmpWidth, tmpRow, Color.FromArgb(color, color, color));
 82                                 }
 83                             }
 84 
 85                             int baseLine = this.fontHeight / 4 * 3;
 86                             graphics.DrawImage(bitmap, cInfo.xoffset,
 87                                 cInfo.yoffset + baseLine - glyph.obj.top);
 88                         }
 89                     }
 90                     else
 91                     { throw new Exception(string.Format("Not support for display the char [{0}]", c)); }
 92                 }
 93 
 94             }
 95 
 96             graphics.Dispose();
 97 
 98             return bigBitmap;
 99         }
100 
101         private void GetTextureBlueprint(FreeTypeFace face, int fontHeight, int maxTextureWidth, out int widthOfTexture, out int heightOfTexture)
102         {
103             widthOfTexture = 0;
104             heightOfTexture = this.fontHeight;
105 
106             int glyphX = 0;
107             int glyphY = 0;
108 
109             for (int i = (int)this.firstChar; i <= (int)this.lastChar; i++)
110             {
111                 char c = Convert.ToChar(i);
112                 FreeTypeBitmapGlyph glyph = new FreeTypeBitmapGlyph(face, c, fontHeight);
113                 bool zeroSize = (glyph.obj.bitmap.rows == 0 && glyph.obj.bitmap.width == 0);
114                 bool zeroBuffer = glyph.obj.bitmap.buffer == IntPtr.Zero;
115                 if (zeroSize && (!zeroBuffer)) { throw new Exception(); }
116                 if ((!zeroSize) && zeroBuffer) { throw new Exception(); }
117                 if (zeroSize) { continue; }
118 
119                 int glyphWidth = glyph.obj.bitmap.width;
120                 int glyphHeight = glyph.obj.bitmap.rows;
121 
122                 if (glyphX + glyphWidth + 1 > maxTextureWidth)
123                 {
124                     heightOfTexture += this.fontHeight;
125 
126                     glyphX = 0;
127                     glyphY = heightOfTexture - this.fontHeight;
128 
129                     CharacterInfo cInfo = new CharacterInfo();
130                     cInfo.xoffset = glyphX; cInfo.yoffset = glyphY;
131                     cInfo.width = glyphWidth; cInfo.height = glyphHeight;
132                     this.charInfoDict.Add(c, cInfo);
133                 }
134                 else
135                 {
136                     widthOfTexture = Math.Max(widthOfTexture, glyphX + glyphWidth + 1);
137 
138                     CharacterInfo cInfo = new CharacterInfo();
139                     cInfo.xoffset = glyphX; cInfo.yoffset = glyphY;
140                     cInfo.width = glyphWidth; cInfo.height = glyphHeight;
141                     this.charInfoDict.Add(c, cInfo);
142                 }
143 
144                 glyphX += glyphWidth + 1;
145             }
146 
147         }
148 
149     }
生成贴图

开源TTF2Bmps下载

根据本篇记录的内容,我写了TTF2Bmps这个程序,可以将任何一个TTF文件解析为BMP图片。你可以在此下载

2015-08-08

TTF2Bmps现在能够获取所有unicode字符的字形,对输入方式也做了改进。 新版的下载地址在此
下面展示了获取某些中文字符的情形。
 
下面展示了获取所有unicode字符的情形。由于整个unicode字符太多,所以只显示了一部分。
 
改进了UI,可以一次指定多个TTF文件,开始计算后有进度条展示进度。下图展示的是生成多个TTF文件的汉字部分贴图。 此版下载地址在这里
 

2015-08-10

改进了UI,可以详细显示进度。可以生成贴图对应的Xml文件(包含贴图每个字形的位置信息)。贴图增加红色虚线标识各行的界限。可选择生成各个字形及其位置信息的列表(多个PNG)。 此版下载地址在这里。
 

2015-08-12

特殊处理空格、tab。调整UI。修复若干bug。
 
 
+BIT祝威+悄悄在此留下版了个权的信息说:

总结

有了贴图,下一步就可以用OpenGL绘制文字了。下回再叙。

如果您愿意花几块钱请我喝杯茶的话,可以用手机扫描下方的二维码,通过支付宝或者微信捐赠。我会努力写出更好的文章。
Thank you for your kindly donation!
 
已标记关键词 清除标记
<p> <strong><span style="font-size:20px;color:#FF0000;">本课程主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者</span></strong> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">1. 包含:<span style="color:#FFFF00;background-color:#FF0000;">项目源码、</span><span style="color:#FFFF00;background-color:#FF0000;">项目文档、数据库脚本、软件工具</span>等所有资料</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">2. 手把手的带你从零开始部署运行本套系统</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">3. 该项目附带的源码资料可作为毕设使用</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">4. 提供技术答疑和远程协助指导</span></strong></span><strong><span style="font-size:18px;"></span></strong> </p> <p> <br /> </p> <p> <span style="font-size:18px;"><strong>项目运行截图:</strong></span> </p> <p> <strong><span style="font-size:18px;">1)系统登陆界面</span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015433522.png" alt="" /><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">2)学生模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015575966.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">3)教师模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016127898.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">4)系统管理员</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016281177.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016369884.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">更多Java毕设项目请关注我的毕设系列课程 <a href="https://edu.csdn.net/lecturer/2104">https://edu.csdn.net/lecturer/2104</a></span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p>
相关推荐
DirectX修复工具(DirectX Repair)是一款系统级工具软件,简便易用。本程序为绿色版,无需安装,可直接运行。 本程序的主要功能是检测当前系统的DirectX状态,如果发现异常则进行修复。程序主要针对0xc000007b问题设计,可以完美修复该问题。本程序中包含了最新版的DirectX redist(Jun2010),并且全部DX文件都有Microsoft的数字签名,安全放心。 本程序为了应对一般电脑用户的使用,采用了易用的一键式设计,只要点击主界面上的“检测并修复”按钮,程序就会自动完成校验、检测、下载、修复以及注册的全部功能,无需用户的介入,大大降低了使用难度。在常规修复过程中,程序还会自动检测DirectX加速状态,在异常时给予用户相应提示。 本程序适用于多个操作系统,如Windows XP(需先安装.NET 2.0,详情请参阅“致Windows XP用户.txt”文件)、Windows Vista、Windows 7、Windows 8、Windows 8.1、Windows 8.1 Update、Windows 10,同时兼容32位操作系统和64位操作系统。本程序会根据系统的不同,自动调整任务模式,无需用户进行设置。 本程序的V4.0版分为标准版、增强版以及在线修复版。所有版本都支持修复DirectX的功能,而增强版则额外支持修复c++的功能。在线修复版功能与标准版相同,但其所需的数据包需要在修复时自动下载。各个版本之间,主程序完全相同,只是其配套使用的数据包不同。因此,标准版和在线修复版可以通过补全扩展包的形式成为增强版。本程序自V3.5版起,自带扩展功能。只要在主界面的“工具”菜单下打开“选项”对话框,找到“扩展”标签,点击其中的“开始扩展”按钮即可。扩展过程需要Internet连接,扩展成功后新的数据包可自动生效。扩展用时根据网络速度不同而不同,最快仅需数秒,最慢需要数分钟,烦请耐心等待。如扩展失败,可点击“扩展”界面左上角小锁图标切换为加密连接,即可很大程度上避免因防火墙或其他原因导致的连接失败。 本程序自V2.0版起采用全新的底层程序架构,使用了异步多线程编程技术,使得检测、下载、修复单独进行,互不干扰,快速如飞。新程序更改了自我校验方式,因此使用新版本的程序时不会再出现自我校验失败的错误;但并非取消自我校验,因此程序安全性与之前版本相同,并未降低。 程序有更新系统c++功能。由于绝大多数软件运行时需要c++的支持,并且c++的异常也会导致0xc000007b错误,因此程序在检测修复的同时,也会根据需要更新系统中的c++组件。自V3.2版本开始使用了全新的c++扩展包,可以大幅提高工业软件修复成功的概率。修复c++的功能仅限于增强版,标准版及在线修复版在系统c++异常时(非丢失时)会提示用户使用增强版进行修复。除常规修复外,新版程序还支持C++强力修复功能。当常规修复无效时,可以到本程序的选项界面内开启强力修复功能,可大幅提高修复成功率。请注意,请仅在常规修复无效时再使用此功能。 程序有两种窗口样式。正常模式即默认样式,适合绝大多数用户使用。另有一种简约模式,此时窗口将只显示最基本的内容,修复会自动进行,修复完成10秒钟后会自动退出。该窗口样式可以使修复工作变得更加简单快速,同时方便其他软件、游戏将本程序内嵌,即可进行无需人工参与的快速修复。开启简约模式的方法是:打开程序所在目录下的“Settings.ini”文件(如果没有可以自己创建),将其中的“FormStyle”一项的值改为“Simple”并保存即可。 新版程序支持命令行运行模式。在命令行中调用本程序,可以在路径后直接添加命令进行相应的设置。常见的命令有7类,分别是设置语言的命令、设置窗口模式的命令,设置安全级别的命令、开启强力修复的命令、设置c++修复模式的命令、控制Direct加速的命令、显示版权信息的命令。具体命令名称可以通过“/help”或“/?”进行查询。 程序有高级筛选功能,开启该功能后用户可以自主选择要修复的文件,避免了其他不必要的修复工作。同时,也支持通过文件进行辅助筛选,只要在程序目录下建立“Filter.dat”文件,其中的每一行写一个需要修复文件的序号即可。该功能仅针对高级用户使用,并且必须在正常窗口模式下才有效(简约模式时无效)。 本程序有自动记录日志功能,可以记录每一次检测修复结果,方便在出现问题时,及时分析和查找原因,以便找到解决办法。 程序的“选项”对话框中包含了7项高级功能。点击"常规”选项卡可以调整程序的基本运行情况,包括日志记录、安全级别控制、调试模式开启等。只有开启调试模式后才能在C
<p> <span style="color:#0000ff;">需要学习ubuntu系统上YOLOv4的同学请前往:《YOLOv4目标检测实战:原理与源码解析》</span> </p> <h3> <span style="color:#3598db;">【为什么要学习这门课】</span> </h3> <p> Linux创始人Linus Torvalds有一句名言:Talk is cheap. Show me the code. <strong><span style="color:#ba372a;">冗谈不够,放码过来!</span></strong> </p> <p> 代码阅读是从基础到提高的必由之路。尤其对深度学习,许多框架隐藏了神经网络底层的实现,只能在上层调包使用,对其内部原理很难认识清晰,不利于进一步优化和创新。 </p> <p> YOLOv4是最近推出的基于深度学习的端到端实时目标检测方法。 </p> <p> YOLOv4的实现darknet是使用C语言开发的轻型开源深度学习框架,依赖少,可移植性好,可以作为很好的代码阅读案例,让我们深入探究其实现原理。 </p> <h3> <span style="color:#3598db;">【课程内容与收获】</span> </h3> <p> 本课程将解析YOLOv4的实现原理和源码,具体内容包括: </p> <p> - YOLOv4目标检测原理 </p> <p> - 神经网络及darknet的C语言实现,尤其是反向传播的梯度求解和误差计算 </p> <p> - 代码阅读工具及方法 </p> <p> - 深度学习计算的利器:BLAS和GEMM </p> <p> - GPU的CUDA编程方法及在darknet的应用 </p> <p> - YOLOv4的程序流程 </p> <p> - YOLOv4各层及关键技术的源码解析 </p> <p> 本课程将提供注释后的darknet的源码程序文件。 </p> <h3> <span style="color:#3598db;">【相关课程】</span> </h3> <p> 除本课程《Windows版YOLOv4目标检测:原理与源码解析》外,本人推出了有关YOLOv4目标检测的系列课程,包括: </p> <p> 《Windows版YOLOv4目标检测实战:训练自己的数据集》 </p> <p> 《Windows版YOLOv4-Tiny目标检测实战:训练自己的数据集》 </p> <p> 《Windows版YOLOv4目标检测实战:人脸口罩佩戴检测》<br /> 《Windows版YOLOv4目标检测实战:中国交通标志识别》 </p> <p> 建议先学习一门YOLOv4实战课程,对YOLOv4的使用方法了解以后再学习本课程。 </p> <h3> <span style="color:#3598db;">【YOLOv4网络模型架构图】</span> </h3> <p> 下图由白勇老师绘制<img alt="" src="https://img-bss.csdnimg.cn/202006291533009066.jpg" /> </p> <p>   </p>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页