欢迎使用优快云-markdown编辑器

原文地址:http://blog.youkuaiyun.com/chenyusiyuan/article/details/6565424

很久没发博客了,趁着近期项目需要,再和大家分享一个小程序,即在OpenCV窗口中创建水平、竖直滚动条来浏览大型图像。如果我们所要显示的图像像素较高,例如1440*900的,而显示器只有 1280*800的分辨率,那么通过cvNamedWindow创建的最大窗口也只能看到部分图像,其余的因为超出窗口大小看不到了,也没有滚动条用来滚动观察其余图像,这样,就不方便我们通过窗口对图像进行交互操作。通常滚动条是在MFC界面上建立的,这方面的例程很多,例如 http://www.opencv.org.cn/forum/viewtopic.php?f=1&t=8349 ;也有使用OpenCV的Trackbar的例子,但Trackbar只有水平滚动、没有垂直方式,而且是按1为步长,使用时不方便、也占用了不少窗口空间。下面这段例程展示了怎样通过 cvSetMouseCallback, cvRect, cvRectangleR, cvResize 等一系列OpenCV函数来创建方便、可随意定制的滚动条。

 

snap1

snap2

 

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
            
            
// Image_ScrollBar.cpp : Defines the entry point for the console application.
//
#include “stdafx.h”
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc_c.h>
#include <iostream>
#include <vector>
using namespace std;
double mx = 0, my = 0;
int dx = 0, dy = 0, horizBar_x = 0, vertiBar_y = 0;
bool clickVertiBar = false, clickHorizBar = false, needScroll = false;
CvRect rect_bar_horiz, rect_bar_verti;
void help()
{
printf(
“/n”
“This program demonstrated the use of the cvSetMouseCallback /n”
“for viewing large image with scroll bar in a small window/n”
“created by OpenCV highgui model. (chenyusiyuan, 2011-06-24)/n”
“Call:/n”
“./Image_ScrollBar [<img_filename default im.jpg> <window_width default 1400> <window_height default 700>]/n/n”
);
}
void mouse_callback( int event, int x, int y, int flags, void* param )
{
if (needScroll)
{
switch( event )
{
case CV_EVENT_LBUTTONDOWN:
mx = x, my = y;
dx = 0, dy = 0;
// 按下左键时光标定位在水平滚动条区域内
if (x >= rect_bar_horiz.x && x <= rect_bar_horiz.x+rect_bar_horiz.width
&& y >= rect_bar_horiz.y && y<= rect_bar_horiz.y+rect_bar_horiz.height)
{
clickHorizBar = true;
}
// 按下左键时光标定位在垂直滚动条区域内
if (x >= rect_bar_verti.x && x <= rect_bar_verti.x+rect_bar_verti.width
&& y >= rect_bar_verti.y && y<= rect_bar_verti.y+rect_bar_verti.height)
{
clickVertiBar = true;
}
break;
case CV_EVENT_MOUSEMOVE:
if (clickHorizBar)
{
dx = fabs(x-mx) > 1 ? (int)(x-mx) : 0;
dy = 0;
}
if (clickVertiBar)
{
dx = 0;
dy = fabs(y-my) > 1 ? (int)(y-my) : 0;
}
mx = x, my = y;
break;
case CV_EVENT_LBUTTONUP:
mx = x, my = y;
dx = 0, dy = 0;
clickHorizBar = false;
clickVertiBar = false;
break;
default:
dx = 0, dy = 0;
break;
}
}
}
void myShowImageScroll(char* title, IplImage* src_img,
int winWidth = 1400, int winHeight = 700) // 显示窗口大小默认为 1400×700
{
IplImage* dst_img;
CvRect rect_dst, // 窗口中有效的图像显示区域
rect_src; // 窗口图像对应于源图像中的区域
int imgWidth = src_img->width,
imgHeight = src_img->height,
barWidth = 25; // 滚动条的宽度(像素)
double scale_w = (double)imgWidth/(double)winWidth, // 源图像与窗口的宽度比值
scale_h = (double)imgHeight/(double)winHeight; // 源图像与窗口的高度比值
if(scale_w<1)
winWidth = imgWidth+barWidth;
if(scale_h<1)
winHeight = imgHeight+barWidth;
int showWidth = winWidth, showHeight = winHeight; // rect_dst 的宽和高
int src_x = 0, src_y = 0; // 源图像中 rect_src 的左上角位置
int horizBar_width = 0, horizBar_height = 0,
vertiBar_width = 0, vertiBar_height = 0;
needScroll = scale_w>1.0 || scale_h>1.0 ? TRUE : FALSE;
// 若图像大于设定的窗口大小,则显示滚动条
if(needScroll)
{
dst_img = cvCreateImage(cvSize(winWidth, winHeight),src_img->depth, src_img->nChannels);
cvZero(dst_img);
// 源图像宽度大于窗口宽度,则显示水平滚动条
if(scale_w > 1.0)
{
showHeight = winHeight - barWidth;
horizBar_width = (int)((double)winWidth/scale_w);
horizBar_height = winHeight-showHeight;
horizBar_x = min(
max(0,horizBar_x+dx),
winWidth-horizBar_width);
rect_bar_horiz = cvRect(
horizBar_x,
showHeight+1,
horizBar_width,
horizBar_height);
// 显示水平滚动条
cvRectangleR(dst_img, rect_bar_horiz, cvScalarAll(255), -1);
}
// 源图像高度大于窗口高度,则显示垂直滚动条
if(scale_h > 1.0)
{
showWidth = winWidth - barWidth;
vertiBar_width = winWidth-showWidth;
vertiBar_height = (int)((double)winHeight/scale_h);
vertiBar_y = min(
max(0,vertiBar_y+dy),
winHeight-vertiBar_height);
rect_bar_verti = cvRect(
showWidth+1,
vertiBar_y,
vertiBar_width,
vertiBar_height);
// 显示垂直滚动条
cvRectangleR(dst_img, rect_bar_verti, cvScalarAll(255), -1);
}
showWidth = min(showWidth,imgWidth);
showHeight = min(showHeight,imgHeight);
// 设置窗口显示区的 ROI
rect_dst = cvRect(0, 0, showWidth, showHeight);
cvSetImageROI(dst_img, rect_dst);
// 设置源图像的 ROI
src_x = (int)((double)horizBar_x*scale_w);
src_y = (int)((double)vertiBar_y*scale_h);
src_x = min(src_x, imgWidth-showWidth);
src_y = min(src_y, imgHeight-showHeight);
rect_src = cvRect(src_x, src_y, showWidth, showHeight);
cvSetImageROI(src_img, rect_src);
// 将源图像内容复制到窗口显示区
cvCopy(src_img, dst_img);
cvResetImageROI(dst_img);
cvResetImageROI(src_img);
// 显示图像和滚动条
cvShowImage(title,dst_img);
cvReleaseImage(&dst_img);
}
// 源图像小于设定窗口,则直接显示图像,无滚动条
else
{
cvShowImage(title, src_img);
}
}
int main(int argc, char** argv)
{
help();
const char* filename = argc > 1 ? argv[1] : “im.jpg”;
int width = 1400, height = 700;
if (4==argc)
{
sscanf( argv[2], “%u”, &width );
sscanf( argv[3], “%u”, &height );
}
cvNamedWindow(“Image Scroll Bar”, 1);
cvSetMouseCallback(“Image Scroll Bar”, mouse_callback);
IplImage* image = cvLoadImage( filename, CV_LOAD_IMAGE_COLOR );
if( !image )
{
fprintf( stderr, “Can not load %s and/or %s/n”
“Usage: Image_ScrollBar [<img_filename default im.jpg>]/n”,
filename );
exit(-1);
}
while(1)
{
myShowImageScroll(“Image Scroll Bar”, image, width, height);
int KEY = cvWaitKey(10);
if( (char) KEY == 27 )
break;
}
cvDestroyWindow(“Image Scroll Bar”);
return 0;
}

//

快捷键

  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y

Markdown及扩展

Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式丰富的HTML页面。 —— [ 维基百科 ]

使用简单的符号标识不同的标题,将某些文字标记为粗体或者斜体,创建一个链接等,详细语法参考帮助?。

本编辑器支持 Markdown Extra ,  扩展了很多好用的功能。具体请参考Github.

表格

Markdown Extra 表格语法:

项目价格
Computer$1600
Phone$12
Pipe$1

可以使用冒号来定义对齐方式:

项目价格数量
Computer1600 元5
Phone12 元12
Pipe1 元234

定义列表

Markdown Extra 定义列表语法: 项目1 项目2
定义 A
定义 B
项目3
定义 C

定义 D

定义D内容

代码块

代码块语法遵循标准markdown代码,例如:

@requires_authorization
def somefunc(param1='', param2=0):
    '''A docstring'''
    if param1 > param2: # interesting
        print 'Greater'
    return (param2 - param1 + 1) or None
class SomeClass:
    pass
>>> message = '''interpreter
... prompt'''

脚注

生成一个脚注1.

目录

[TOC]来生成目录:

数学公式

使用MathJax渲染LaTex 数学公式,详见math.stackexchange.com.

  • 行内公式,数学公式为: Γ(n)=(n1)!nN
  • 块级公式:

x=b±b24ac2a

更多LaTex语法请参考 这儿.

UML 图:

可以渲染序列图:

Created with Raphaël 2.1.0 张三 张三 李四 李四 嘿,小四儿, 写博客了没? 李四愣了一下,说: 忙得吐血,哪有时间写。

或者流程图:

Created with Raphaël 2.1.0 开始 我的操作 确认? 结束 yes no
  • 关于 序列图 语法,参考 这儿,
  • 关于 流程图 语法,参考 这儿.

离线写博客

即使用户在没有网络的情况下,也可以通过本编辑器离线写博客(直接在曾经使用过的浏览器中输入write.blog.youkuaiyun.com/mdeditor即可。Markdown编辑器使用浏览器离线存储将内容保存在本地。

用户写博客的过程中,内容实时保存在浏览器缓存中,在用户关闭浏览器或者其它异常情况下,内容不会丢失。用户再次打开浏览器时,会显示上次用户正在编辑的没有发表的内容。

博客发表后,本地缓存将被删除。 

用户可以选择 把正在写的博客保存到服务器草稿箱,即使换浏览器或者清除缓存,内容也不会丢失。

注意:虽然浏览器存储大部分时候都比较可靠,但为了您的数据安全,在联网后,请务必及时发表或者保存到服务器草稿箱

浏览器兼容

  1. 目前,本编辑器对Chrome浏览器支持最为完整。建议大家使用较新版本的Chrome。
  2. IE9以下不支持
  3. IE9,10,11存在以下问题
    1. 不支持离线功能
    2. IE9不支持文件导入导出
    3. IE10不支持拖拽文件导入


  1. 这里是 脚注内容.
### 基于Unity3D的ACT游戏的设计与实现 #### 摘要与关键词解析 本项目聚焦于使用Unity3D引擎开发一款2D动作类游戏(ACT),旨在为玩家提供沉浸式的游戏体验以及成就感。游戏开发过程中,作者不仅关注游戏的核心玩法,还深入探讨了如何利用Unity内置的各种工具和技术来提升游戏性能、改善用户体验。 **关键词**: - **Unity**:一个跨平台的综合游戏开发引擎,支持2D和3D游戏开发。 - **ScriptableObject**:Unity中的一种特殊脚本类型,用于存储数据和配置信息,方便在多个场景间共享。 - **游戏开发**:涵盖了游戏设计、编程、美术创作等多个方面的工作。 - **2D游戏**:指采用二维画面的游戏,相比3D游戏,具有更简洁的视觉风格和较低的技术门槛。 - **状态机**:一种常用的编程模式,用于管理游戏对象的状态转换,如角色的动作变化等。 - **Cinemachine**:Unity的一个插件,提供了高级的相机控制系统,能够创建出电影级的摄像机动画效果。 #### 第1章:绪论 在本章中,作者首先阐述了游戏开发的背景及意义。随着科技的进步,数字娱乐已经成为人们生活中不可或缺的一部分,而游戏作为其中的一种形式,更是受到了广泛的关注。游戏不仅能够提供娱乐,还能培养玩家的逻辑思维能力和解决问题的能力。因此,开发高质量的游戏产品显得尤为重要。 随后,作者介绍了本项目的起源和发展过程,包括为何选择Unity作为开发工具,以及项目的目标和预期成果。此外,作者还提到了Unity引擎的特点及其在游戏开发中的优势,比如跨平台兼容性、丰富的资源库、强大的社区支持等。 #### 技术选型与实现细节 1. **C#语言**:Unity主要使用的编程语言是C#,它是一种面向对象的语言,具有良好的可读性和扩展性。在本项目中,C#被用来编写游戏逻辑、实现用户交互等功能。 2. **UGUI和Text Mesh Pro**:UGUI是Unity提供的用户界面系统,可以轻松地创建各种界面元素,如按钮、滑块等。Text Mesh Pro则是一款高级文本渲染插件,能够提高文本的渲染质量和性能,使得游戏中的文字更加清晰易读。 3. **有限状态机**:状态机是一种常见的游戏开发模式,用于管理和控制游戏对象的不同状态。在本项目中,状态机被用来处理游戏角色的动作变化,例如攻击、跳跃、行走等。通过这种方式,可以更加高效地组织代码,提高游戏逻辑的清晰度和可维护性。 4. **ScriptableObject**:这是一种特殊的脚本类型,在Unity中主要用于存储数据和配置信息。通过ScriptableObject,开发者可以在编辑器中直接编辑这些数据,而无需重启游戏。这种机制极大地提高了开发效率,并且使得多人协作变得更加容易。 5. **物理系统**:Unity内置的物理引擎能够模拟真实的物理行为,如重力、碰撞等。在本项目中,物理系统被用来处理角色和环境之间的互动,确保游戏中的物理效果逼真可靠。 #### 测试与优化 为了确保游戏的质量,作者进行了多轮的测试,包括功能测试、性能测试以及玩家体验测试。通过不断地调整和优化,最终实现了游戏在低配置设备上的流畅运行。 **总结**: 通过上述分析可以看出,《基于Unity3D的ACT游戏的设计与实现》项目不仅关注游戏本身的玩法设计,还深入探讨了如何利用先进的技术和工具来提高游戏的品质。从技术选型到具体实现,再到后期的测试与优化,每一个环节都体现了作者的专业水平和对游戏开发的热情。对于想要进入游戏开发领域的初学者来说,该项目提供了一个非常好的学习案例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值