- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
对于一个学校项目,我们的信息学老师希望我们重新发明轮子。我们给出了一个数组,表示图像的像素,其中包含在另一个脚本中定义的颜色对象。它们代表一组 4 个整数,红色、绿色、蓝色和 Alpha 值的值为 0 到 255。现在我们必须对该数组进行图像处理的标准操作。我们被明确告知,要使用 Internet 和问题站点(例如堆栈溢出)作为引用。
对此我没有办法:如何将给定的 Colour-Object-Array 转换为表示相同图像但旋转 x 度(扩展)的另一个数组。新的颜色/像素在哪里着陆,如何计算?如何计算这个数组的新大小?有没有任何易于理解的pdf,我可以通过,理解,如何,fe。 PIL image.rotate(expand=true) 算法在理论上是可行的,或者有人可以解释如何做到这一点吗?我会喜欢伪代码或 python 3,因为它是我唯一能理解的编程语言。
此类数组的简短示例:
BLUE = Colour(0 ,0 ,255,255)
BLACK = Colour(0 ,0 ,0 ,255)
WHITE = Colour(255,255,255,255)
Array = [ [BLUE , BLACK, WHITE, BLUE ],
[BLACK, BLACK, BLUE , WHITE],
[WHITE, WHITE, BLUE , WHITE] ]
编辑:要访问颜色值,有方法 getred()、getgreen()、getblue() 和 gettuple() - 我已经实现了“画家”算法,这意味着颜色可以是通过调用 merge(bottomColour, topColour) 进行合并,如果一个颜色位于另一个之上,则返回结果颜色。这方面的理论可以在这里找到: Determine RGBA colour received by combining two colours
我们不允许使用 numpy 或任何其他模块或库。没有颜色/像素的地方应该是“无”。
非常感谢!
最佳答案
我们需要将旋转图像中的每个坐标映射到原始图像中的相应坐标。
假设围绕(a, b)
旋转并逆时针旋转θ
度:
其中 (x, y)
是原始图像,(x', y')
是旋转后的图像。
简单技术:最近邻
当使用计算出的坐标对像素数据进行采样时,我们可以简单地将它们四舍五入到最接近的整数(即最近的像素)。这给出了以下结果:
乍一看这似乎足够好,但网页重新缩放 + 图像压缩模糊了边缘。放大 View 显示生成的图像具有令人讨厌的锯齿状边缘(锯齿):
过滤:双线性近似
为了改进这一点,我们需要意识到旋转后的“像素”区域实际上覆盖了原始图像中的多个像素:
然后,我们可以将平均像素颜色计算为每个覆盖的原始像素的贡献总和,这些原始像素按其相关面积加权。为了方便起见,我们称其为“各向异性”过滤(不是该术语的确切含义,而是我能想到的最接近的含义)。
然而,这些区域将很难准确计算。所以我们可以通过应用一个近似值来“作弊”一点,其中旋转的样本区域(红色)与网格线对齐:
这使得面积更容易计算。我们将使用一阶线性平均法——“双线性”过滤。
C# 代码示例:
Transform trn = new Transform(a, cx, cy); // inverse rotation transform to original image space
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
Vector v = trn.Get((float)x, (float)y);
int i = (int)Math.Floor(v.x),
j = (int)Math.Floor(v.y);
float s = v.x - (float)i,
t = v.y - (float)j;
RGB c = RGB.Black, u; float z, r = 0.0f;
if ((u = src.getPixel(i, j)).Valid)
{
z = (1 - s) * (1 - t); // area of overlap in top-left covered pixel
c += u * z; r += z; // add to total color and total area
}
if ((u = src.getPixel(i + 1, j)).Valid)
{
z = s * (1 - t);
c += u * z; r += z;
}
if ((u = src.getPixel(i, j + 1)).Valid)
{
z = (1 - s) * t;
c += u * z; r += z;
}
if ((u = src.getPixel(i + 1, j + 1)).Valid)
{
z = s * t;
c += u * z; r += z;
}
if (r > 0.0f)
dst.setPixel(x, y, c * (1.0f / r)); // normalize the sum by total area
}
}
放大结果:
比朴素的最近邻方法好得多!
强制症警报!
出于好奇,我实现了之前提到的完整“各向异性”方法。花费的时间比应该的长,而且效率不高(使用 Sutherland-Hodgman 裁剪来计算旋转像素区域和每个网格像素之间的交叉区域)。计算时间达到顶峰 - 大约 7 秒,而双线性方法不到 0.5 秒。最后的结果?根本不值得付出努力!
(L:双线性,R:各向异性)
代码(我的实现很垃圾,不要费心去读它,真的):
private static Vector[][] clipboxes = new Vector[][] {
new Vector[] { new Vector(-1f,-1f), new Vector(0f,-1f), new Vector(0f,0f), new Vector(-1f,0f)},
new Vector[] { new Vector(0f,-1f), new Vector(1f,-1f), new Vector(1f,0f), new Vector(0f,0f)},
new Vector[] { new Vector(1f,-1f), new Vector(2f,-1f), new Vector(2f,0f), new Vector(1f,0f)},
new Vector[] { new Vector(-1f,0f), new Vector(0f,0f), new Vector(0f,1f), new Vector(-1f,1f)},
new Vector[] { new Vector(0f,0f), new Vector(1f,0f), new Vector(1f,1f), new Vector(0f,1f)},
new Vector[] { new Vector(1f,0f), new Vector(2f,0f), new Vector(2f,1f), new Vector(1f,1f)},
new Vector[] { new Vector(-1f,1f), new Vector(0f,1f), new Vector(0f,2f), new Vector(-1f,2f)},
new Vector[] { new Vector(0f,1f), new Vector(1f,1f), new Vector(1f,2f), new Vector(0f,2f)},
new Vector[] { new Vector(1f,1f), new Vector(2f,1f), new Vector(2f,2f), new Vector(1f,2f)}
};
private static bool inside(Vector a, Vector b, Vector c)
{
return ((c - b) ^ (a - b)) > 0f;
}
private static Vector intersect(Vector a, Vector b, Vector c, Vector d)
{
return (((c - d) * (a ^ b)) - ((a - b) * (c ^ d))) * (1.0f / ((a - b) ^ (c - d)));
}
private static float getArea(List<Vector> l)
{
if (l.Count == 0)
return 0f;
float sum = 0.0f;
Vector b = l.Last();
foreach (Vector c in l)
{
sum += b ^ c;
b = c;
}
return 0.5f * Math.Abs(sum);
}
private static float getOverlap(Vector[] clip, Vector[] box)
{
List<Vector> lO = box.ToList();
Vector lC = clip[clip.Length - 1];
foreach (Vector C in clip)
{
if (lO.Count == 0)
return 0.0f;
List<Vector> lI = lO;
Vector lB = lI.Last();
lO = new List<Vector>();
foreach (Vector B in lI)
{
if (inside(B, lC, C))
{
if (!inside(lB, lC, C))
lO.Add(intersect(lB, B, lC, C));
lO.Add(B);
}
else
if (inside(lB, lC, C))
lO.Add(intersect(lB, B, lC, C));
lB = B;
}
lC = C;
}
return getArea(lO);
}
// image processing code, as before
Transform trn = new Transform(a, cx, cy);
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
Vector p = trn.Get((float)x, (float)y);
int i = p.X, j = p.Y;
Vector d = new Vector(i, j);
List<Vector> r = new List<Vector>();
r.Add(p - d);
r.Add(trn.Get((float)(x+1), (float)y) - d);
r.Add(trn.Get((float)(x+1), (float)(y+1)) - d);
r.Add(trn.Get((float)x, (float)(y+1)) - d);
RGB c = RGB.Black;
float t = 0.0f;
for (int l = 0; l < 3; l++)
{
for (int m = 0; m < 3; m++)
{
float area = getOverlap(clipboxes[m * 3 + l], r.ToArray());
if (area > 0.0f)
{
RGB s = src.getPixel(i + l - 1, j + m - 1);
if (s.Valid)
{
c += s * area;
t += area;
}
}
}
}
if (t > 0.0f)
dst.setPixel(x, y, c * (1.0f / t));
}
}
还有更高级的技术可用,例如使用傅立叶变换 - 请参阅达特茅斯大学名为 High Quality Alias Free Image Rotation 的论文(可直接从其网站获取)。此外,我们可以使用更高阶的代替双线性插值,例如双三次,这会产生更平滑的结果。
关于python - 将二维数组中的像素数据旋转 x 度(伪代码或 Python3),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44761028/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!