[视觉错觉] 隐藏的爱心

群里的作业,睡觉前完成了。

一个有趣的视觉错觉程序。

执行效果如下:

PS:程序执行后可能有点大,效果不太明显,那就离远点看试试。

完整的源代码如下:

////////////////////////////////////////
// 程序:视觉错觉:隐藏的爱心
// 作者:BestAns
// 编译环境:VS2019,EasyX_20211109
// 编写日期:2021-11-29
//
#include <graphics.h> 
#include <conio.h>

const int UNIT = 43;

// 画背景单元方格
void DrawBlock(int x, int y, bool odd)
{
	int c1, c2;
	if (odd) { c1 = BLACK; c2 = WHITE; }
	else	 { c1 = WHITE; c2 = BLAC
...

令小也画作绘制

绘制过程

首先需要一幅绘制好的画作,这里我用的是令小也的作品,通过观察寻找绘制的规律,然后分析绘制的层次。

在用程序绘制比较复杂的画作时,一定要耐心,将画作的层次分析清楚,可以大大节省很多代码量。一般都是将复杂的图形用简单的图形进行拼接,覆盖等方式进行绘制。

截图

源码

///////////////////////////////////////////////////
// 程序名称:图像绘制
// 编译环境:Mictosoft Visual Studio 2013, EasyX_20200315(beta)
// 作    者:luoyh <2864292458@qq.com>
// 学    校:河南理工大学
// 最后修改:2021-11-26
//

#include<graphics.h>
#include<conio.h>
#include<
...

傅里叶圆圈画图

令 k = ( -N , ... , -2, -1, 0, 1, 2, ... N ) ,我们设置 2N + 1 个向量,每个向量旋转速度是 k 圈每秒,我们只需要设置这些向量的模长和初始位置,理论上就能画出任意图形。

具体请观看 3Blue1Brown 视频

/*
*  作者:孙小鱼
*  QQ:1226598193
*实现原理:https://www.bilibili.com/video/BV1vt411N7Ti
*/
#include <graphics.h>
#include <conio.h>
#include <vector>
#include <cmath>
#include <algorithm>


#define X(x) ( (x) + (xScreen * 0.5f))
#define Y(y) (-(y) + (yScreen * 0.5f
...

量角器

编写过程

该程序借鉴了以前编写的时钟罗盘,以及参考官网上窗口技巧实现圆形窗口。实现了一个简单的量角器程序,可以通过量角器测量一些简单图形的角度弧度等信息。

编写灵感

我在绘制图形时,需要使用 arc 这个函数,但是该函数的参数获取比较麻烦,需要获得的弧的起始角度和终止角度。那这个角度如何获取呢,其实办法有很多,例如将要绘制的图像导入到 CAD 中直接就可以量,也可以用量角器量,或者手机下载软件来量,但是最终的麻烦程度超过了写一个程序所需要的时间。所以我索性编写了一个量角器,来解决编写程序过程中遇到的麻烦。程序本来就是来解决麻烦的,而不是制造麻烦的。

使用方式

鼠标左键长按到红色的圈上可以实现量角器的拖拽,左键点击外边红色的圈可以实现量测,右键点击红色的圈退出程序。

截图

量角器

源码

...

提取图像直方图(图像处理)

继直方图规定化后的研究

由于直方图规定化是根据两张图片的累计直方图进行图像的处理。对于这个处理过程,我尝试了很图像进行替换色系,但是没有找到一个相对合适案例,来体现直方图规定化这个算法的精妙之处。在多次尝试中,我发现一个灰度图像(原图)和一个彩色图像(规定化图)进行直方图规定化处理后,就会得到一个彩色的图像。

我的发现

我们都知道,灰度图像转换为彩色图形,一般情况下都是假彩色。如何将一个灰度图像进行还原成原本的彩色图像,那就是我们需要获得彩色图像的直方图。

创新之处

我利用彩色图像,生成一个色条,该色条与宽度无关。也就是说,我用 1 个像素宽,n 个像素长的有颜色的色条,就可以储存该图像的直方图。通过该色条与一张灰度图像,使用直方图规定化算法就可以将彩色图像还原出来。

具体的用处

  1. 一种新的图像储存方式,使得图像的存储空间更小。
  2. 作为直方图规定化的后续研究提供另一种思路。
  3. 解决一些需要由灰度图像转换为彩色图像的便
...

贝塞尔曲线

动态演示贝塞尔曲线的绘制过程。

支持任意点数、任意阶次。

点击鼠标右键,在鼠标位置将创建新的点。

按住鼠标左键拖动控制点。

空格键屏幕将清空。

一起来玩一玩吧!

/////////////////////////////////////////////////////////////
// 程序名称:贝塞尔曲线
// 编译环境:Visual Studio 2019 (v142) x86,EasyX_20211109_x86
// 作  者:luyiran <872289455@qq.com>
// 发布日期:2021-11-18
//
#include <math.h>				// sin
#include <stdint.h>				// uint64_t
#include <vector>				// array
...

直方图规定化(图像处理)

直方图规定化说明

简单说明一下直方图,就是对图像的像素值的个数进行统计,然后分别计算出每一种像素值所占所有像素数量(图像大小)的比例。累计直方图就是将统计起来算好的比例依次累加。举个例子,当像素值为 1 时它所占得比例所对应的累计比例就是它本身。而像素值为 2 时它的累计比例就是像素值为 1 时的比例加上像素值为 2 时的比例。依次类推,像素值为 255 时,所对应的累计比例为 1。

直方图规定化的操作就是计算两张图片的累计直方图,然后进行对应的计算,将一个图片的色系替换给另一个图片。(个人理解,仅供参考)

处理图片介绍

这里我选用了一张小王子的图片作为需要处理的图片,一张不同颜色比例分布的图片。将不同颜色比例的照片的色系替换掉小王子的色系,生成一张新色系的图片。如果感兴趣,还可以尝试其他图片,不同的图片效果不同。

图片显示


图1 原图


...

使用 EasyX 实现 UI 原理教程(章三 基础 UI 程序的结构与基础按钮)

返回:本文目录

正文

在开始第三章的学习之前,我们先来理解几个概念:

1. 父与子

如上图所示,Form 1 窗口下有一 LineText 3 控件与 Button 2 控件,假设 LineText 3 与 Button 2 是 Form1 下一控件,那么我们便说 Form 1 是 LineText 3 与 Button 2 的“父亲”,相对的 LineText 3 与 Button 2 我们叫做“儿子”,专业点说 LineText 3 与 Button 2 是 Form 1 的子控件,Form 1 是 Button 2 与 LineText 3 的父窗口。

2. 事件(Event)

如果你有略微接触过 Win32 Api 的话,你肯定知道“事件”的概念,事件,简单来说就是用户的任意交互(例如:点击鼠标,移动鼠标,按下键盘)

...

使用 EasyX 实现 UI 原理教程(章二 绘图单元)

返回:本文目录

布局在一个界面上的形形色色的控件我们都可以叫他为一个单元 ( cell )。

如上图所示,任意一个控件(不论它是否能与用户发生交互,图形规律与否)都是一个单元, 上一篇文章 我们已经学会了触发器以及相关实现,那么,我们将一个控件比作一个动物细胞,我们可以说触发器是细胞核,而绘图单元则是细胞膜,两者缺一不可,触发器负责处理用户点击,而绘图单元则负责展示画面。

接下来,我们将上一篇文章所写的触发器封装为 “trigger.h”(文件内容上一章已标注),然后再来开始今天的代码学习,由刚刚的介绍我们知道,绘图单元是负责将控件画出来的,所以不同的控件要拥有不同的绘图单元,那么我们首先创建一个根据图形贴图的绘图单元,因为绘图单元和触发器缺一不可,所以我们的绘图单元要派生于异形触发器 "geometry_trigger" 类。

接下来,我们来大概设计一下一个基础的贴图绘图单元:

这边解释

...

使用 EasyX 实现 UI 原理教程(章一 触发器)

返回:本文目录

触发器是判断鼠标是否浮动到控件上的判断器,分为两大类:

1. 异形触发器。

2. 矩形触发器。

先说矩形触发器吧。

如上图,这是一个使用 fillreactangle 函数画出来的矩形,这个时候让你想办法判断鼠标是否点击了该矩形,你一定会想到,用鼠标 x、y 坐标与矩形 x、y 坐标和长、宽来解决,确实这是一个方法,这里放一下伪代码:

// 伪代码
如果 (鼠标_x >= 矩形_x && 鼠标_x <= 矩形_x + 矩形长 &&
	  鼠标_y >= 矩形_y && 鼠标_y <= 矩形_y + 矩形宽)
{
	鼠标点击处理();
}

基于上面的逻辑,我们尝试在 C++ 中把他封装成类:

...

使用 EasyX 实现 UI 原理教程

前言

关于 EasyX 实现控件,已经有很多人给出过了大概实例甚至是一个完整的控件库,但是很少有人能接触到这部分底层UI原理。

本文主意在于让大家了解自绘 UI 控件的原理和大概实现过程,其余过多细节不做过多赘述,若有同学有兴趣写一个基于 EasyX 的控件库本文章或许会有帮助。

本文也会将在 EasyX 中写控件库项目的坑与细节指出,避免各位走过多的弯路~

目录

第一章 触发器

第二章 绘图单元

第三章 基础 UI 程序的结构与基础按钮

未完待续...

图像旋转(图像处理)

图像旋转说明

虽然在 EasyX 中有专门的图像旋转的函数,但是这个函数只是实现了图像旋转的这个功能。其中具体的旋转实现过程就像是个黑匣子一样,而且该函数旋转之后的图像显示不够完整。针对以上问题,我使用双线性内插法,实现了一个比较完整的图像旋转算法。

我对图像旋转的理解

图像旋转是宏观,而旋转的过程是微观的。我们看到的是一个图像整体的旋转,实现整体旋转的过程是每一个像素值位置的移动。

关于移动的方式,分为直接法和间接法。直接法是由原图像的像素位置去计算旋转后图像的位置,间接法是有旋转后图像的位置去反算原图的位置从而获得像素值。这里我使用的是间接法。间接法又存在一个问题,就是由旋转后图像的每一个位置反算到原图时,所在的坐标可能不是一个整数坐标。那么这个坐标我们给它的像素值就需要内插出来。

关于内插,又分为最近邻元法,双线性内插法,三次内插法。这里使用的是双线性内插法,它的算法简单来说,就是根据距离周围四个像素值的远近,离得越近,权重越大,来内插一个像素值。(个人理解,仅供参考)

示例图像

...

手动摆放七巧板

游戏介绍

手动摆放七巧板的程序,可以拼成各种图案,也可以再添加一套七巧板一起拼。

操作方法:

  • 鼠标左键拖动图形;
  • 鼠标右键使七巧板顺时针旋转 45 度;
  • 按住左键时按空格可以让四边形轴对称翻转。

游戏截图

完整游戏源代码

完整的 VC 项目在 gitee 上:https://gitee.com/ProtagonistMan/tangram

编译环境

VisualStudio 2019,EasyX_20200902

文件描述

Point.h

用于存三角形和四边形的点的值,用整型限制很多,例如求一个点相对于一个圆心旋转一定角度后的位置,我的做法是用三角函数来求,就是半径长度乘以三角函数值得到 x,y 的坐标,最终结果一定是小数,如果这个值不保存下来,而是强转为整型,那么这个点的位置就不准确,下次旋转时得

...

素描算法(图像处理)

素描算法介绍

素描算法其实就是几种简单的图像处理算法,对同一张图片进行处理后,产生的一种类似素描的算法。这里简单的描述一下他的原理。

  1. 彩色图像进行类似直方图均衡化处理,增强图像的对比度,使得图像的轮廓更加分明。
  2. 将步骤 1 处理后的彩色图像进行灰度处理得到图像 gray。
  3. 将得到的图像 gray 复制一份得到图像 gray1。
  4. 将图像 gray 的像素进行取反,得到负片效果。
  5. 对步骤 4 获得的图像进行高斯滤波处理。这里高斯滤波处理次数不同,最后的效果也不同。处理得到图像 guassian。
  6. 图像淡化生成素描图像 sketch。

处理的图像效果

图1 原图

图2 素描算法

...

舒尔特方格小游戏

游戏介绍

学校的心理课上介绍了舒尔特方格这个东西,能锻炼自己的专注力,回家以后写了 300 来行代码实现了这个舒尔特方格小游戏。

玩法就是按照 1~25 的顺序去点击数字,时间越短越好。

更新日志 (2021/11/27) : 对游戏进行大改,重写 UI,加入计分系统

游戏截图

游戏源码下载

这里直接上源码,同学们可以自行复制到自己的编译器里编译。

#include <graphics.h>
#include <conio.h>

#include <fstream>

#include <vector>
#include <algorithm>
#include <string>

#pragma comm
...