- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
使用双线性插值将2x2矩阵放大到5x5的示例程序。
对于这种简单的情况,OpenCV产生的结果在边界处有伪像。
gy, gx = np.mgrid[0:2, 0:2]
gx = np.float32(gx)
print(gx)
res = cv2.resize(gx,(5,5), fx=0, fy=0, interpolation=cv2.INTER_LINEAR)
print(res)
[[ 0. 1.]
[ 0. 1.]]
[[ 0. 0.1 0.5 0.89999998 1. ]
[ 0. 0.1 0.5 0.89999998 1. ]
[ 0. 0.1 0.5 0.89999998 1. ]
[ 0. 0.1 0.5 0.89999998 1. ]
[ 0. 0.1 0.5 0.89999998 1. ]]
[[0 0.25 0.5 0.75 1
0 0.25 0.5 0.75 1
0 0.25 0.5 0.75 1
0 0.25 0.5 0.75 1
0 0.25 0.5 0.75 1]]
最佳答案
TL; DR
我使用其他图像处理库(scikit-image,Pillow和Matlab)进行了测试,但它们均未返回预期的结果。
奇怪的是,这种行为是由于执行双线性插值以获取有效结果的方法或某种程度上的约定而不是我认为的错误所致。
我已经发布了一个示例代码,以通过双线性插值来执行图像大小调整(当然,检查是否还可以,我不确定如何正确处理图像索引...),该图像可以输出预期的结果。
对问题的部分答案。
其他一些图像处理库的输出是什么?
scikit图像
Python模块scikit-image包含许多图像处理算法。这里是 skimage.transform.resize
方法的输出(skimage.__version__: 0.12.3
):
mode='constant'
(默认)import numpy as np
from skimage.transform import resize
image = np.array( [
[0., 1.],
[0., 1.]
] )
print 'image:\n', image
image_resized = resize(image, (5,5), order=1, mode='constant')
print 'image_resized:\n', image_resized
image:
[[ 0. 1.]
[ 0. 1.]]
image_resized:
[[ 0. 0.07 0.35 0.63 0.49]
[ 0. 0.1 0.5 0.9 0.7 ]
[ 0. 0.1 0.5 0.9 0.7 ]
[ 0. 0.1 0.5 0.9 0.7 ]
[ 0. 0.07 0.35 0.63 0.49]]
mode='edge'
image:
[[ 0. 1.]
[ 0. 1.]]
image_resized:
[[ 0. 0.1 0.5 0.9 1. ]
[ 0. 0.1 0.5 0.9 1. ]
[ 0. 0.1 0.5 0.9 1. ]
[ 0. 0.1 0.5 0.9 1. ]
[ 0. 0.1 0.5 0.9 1. ]]
mode='symmetric'
image:
[[ 0. 1.]
[ 0. 1.]]
image_resized:
[[ 0. 0.1 0.5 0.9 1. ]
[ 0. 0.1 0.5 0.9 1. ]
[ 0. 0.1 0.5 0.9 1. ]
[ 0. 0.1 0.5 0.9 1. ]
[ 0. 0.1 0.5 0.9 1. ]]
mode='reflect'
image:
[[ 0. 1.]
[ 0. 1.]]
image_resized:
[[ 0.3 0.1 0.5 0.9 0.7]
[ 0.3 0.1 0.5 0.9 0.7]
[ 0.3 0.1 0.5 0.9 0.7]
[ 0.3 0.1 0.5 0.9 0.7]
[ 0.3 0.1 0.5 0.9 0.7]]
mode='wrap'
image:
[[ 0. 1.]
[ 0. 1.]]
image_resized:
[[ 0.3 0.1 0.5 0.9 0.7]
[ 0.3 0.1 0.5 0.9 0.7]
[ 0.3 0.1 0.5 0.9 0.7]
[ 0.3 0.1 0.5 0.9 0.7]
[ 0.3 0.1 0.5 0.9 0.7]]
constant
)产生不同的输出,但是边缘模式返回的结果与OpenCV相同。调整大小模式均未产生预期的结果。
is the friendly PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lundh and Contributors.
PIL.Image.Image.resize
(
PIL.__version__: 4.0.0
)呢?
import numpy as np
from PIL import Image
image = np.array( [
[0., 1.],
[0., 1.]
] )
print 'image:\n', image
image_pil = Image.fromarray(image)
image_resized_pil = image_pil.resize((5,5), resample=Image.BILINEAR)
print 'image_resized_pil:\n', np.asarray(image_resized_pil, dtype=np.float)
image:
[[ 0. 1.]
[ 0. 1.]]
image_resized_pil:
[[ 0. 0.1 0.5 0.89999998 1. ]
[ 0. 0.1 0.5 0.89999998 1. ]
[ 0. 0.1 0.5 0.89999998 1. ]
[ 0. 0.1 0.5 0.89999998 1. ]
[ 0. 0.1 0.5 0.89999998 1. ]]
Pillow
图像大小调整与OpenCV库的输出匹配。
imresize
可以调整图像大小。
image = zeros(2,1,'double');
image(1,2) = 1;
image(2,2) = 1;
image
image_resize = imresize(image, [5 5], 'bilinear')
image =
0 1
0 1
image_resize =
0 0.1000 0.5000 0.9000 1.0000
0 0.1000 0.5000 0.9000 1.0000
0 0.1000 0.5000 0.9000 1.0000
0 0.1000 0.5000 0.9000 1.0000
0 0.1000 0.5000 0.9000 1.0000
2x2
图像放大到
4x4
图像时发生的情况:
(0,0)
的目标像素将获得
(0,0)
的源像素的值以及
(0,1)
,
(1,0)
和
(1,1)
的像素。
(0,0)
上的目标像素将获得一个值,该值是源图像中4个邻居的线性组合:
The four red dots show the data points and the green dot is the point at which we want to interpolate.
R1
的计算公式为:
R1 = ((x2 – x)/(x2 – x1))*Q11 + ((x – x1)/(x2 – x1))*Q21
。
R2
的计算公式为:
R2 = ((x2 – x)/(x2 – x1))*Q12 + ((x – x1)/(x2 – x1))*Q22
。
P
计算为
R1
和
R2
:
P = ((y2 – y)/(y2 – y1))*R1 + ((y – y1)/(y2 – y1))*R2
的加权平均值。
[0, 1]
之间标准化的坐标可简化
formula。
cv::Mat
一起工作:
#include <iostream>
#include <opencv2/core.hpp>
float lerp(const float A, const float B, const float t) {
return A * (1.0f - t) + B * t;
}
template <typename Type>
Type resizeBilinear(const cv::Mat &src, const float u, const float v, const float xFrac, const float yFrac) {
int u0 = (int) u;
int v0 = (int) v;
int u1 = (std::min)(src.cols-1, (int) u+1);
int v1 = v0;
int u2 = u0;
int v2 = (std::min)(src.rows-1, (int) v+1);
int u3 = (std::min)(src.cols-1, (int) u+1);
int v3 = (std::min)(src.rows-1, (int) v+1);
float col0 = lerp(src.at<Type>(v0, u0), src.at<Type>(v1, u1), xFrac);
float col1 = lerp(src.at<Type>(v2, u2), src.at<Type>(v3, u3), xFrac);
float value = lerp(col0, col1, yFrac);
return cv::saturate_cast<Type>(value);
}
template <typename Type>
void resize(const cv::Mat &src, cv::Mat &dst) {
float scaleY = (src.rows - 1) / (float) (dst.rows - 1);
float scaleX = (src.cols - 1) / (float) (dst.cols - 1);
for (int i = 0; i < dst.rows; i++) {
float v = i * scaleY;
float yFrac = v - (int) v;
for (int j = 0; j < dst.cols; j++) {
float u = j * scaleX;
float xFrac = u - (int) u;
dst.at<Type>(i, j) = resizeBilinear<Type>(src, u, v, xFrac, yFrac);
}
}
}
void resize(const cv::Mat &src, cv::Mat &dst, const int width, const int height) {
if (width < 2 || height < 2 || src.cols < 2 || src.rows < 2) {
std::cerr << "Too small!" << std::endl;
return;
}
dst = cv::Mat::zeros(height, width, src.type());
switch (src.type()) {
case CV_8U:
resize<uchar>(src, dst);
break;
case CV_64F:
resize<double>(src, dst);
break;
default:
std::cerr << "Src type is not supported!" << std::endl;
break;
}
}
int main() {
cv::Mat img = (cv::Mat_<double>(2,2) << 0, 1, 0, 1);
std::cout << "img:\n" << img << std::endl;
cv::Mat img_resize;
resize(img, img_resize, 5, 5);
std::cout << "img_resize=\n" << img_resize << std::endl;
return EXIT_SUCCESS;
}
img:
[0, 1;
0, 1]
img_resize=
[0, 0.25, 0.5, 0.75, 1;
0, 0.25, 0.5, 0.75, 1;
0, 0.25, 0.5, 0.75, 1;
0, 0.25, 0.5, 0.75, 1;
0, 0.25, 0.5, 0.75, 1]
resize()
函数不太可能出错,因为我可以测试的其他图像处理库都不能产生预期的输出,而且可以通过良好的参数产生相同的OpenCV输出。
关于OpenCV resize()结果是否错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43598373/
我有一个 if 语句,如下所示 if (not(fullpath.lower().endswith(".pdf")) or not (fullpath.lower().endswith(tup
然而,在 PHP 中,可以: only appears if $foo is true. only appears if $foo is false. 在 Javascript 中,能否在一个脚
XML有很多好处。它既是机器可读的,也是人类可读的,它具有标准化的格式,并且用途广泛。 它也有一些缺点。它是冗长的,不是传输大量数据的非常有效的方法。 XML最有用的方面之一是模式语言。使用模式,您可
由于长期使用 SQL2000,我并没有真正深入了解公用表表达式。 我给出的答案here (#4025380)和 here (#4018793)违背了潮流,因为他们没有使用 CTE。 我很欣赏它们对于递
我有一个应用程序: void deleteObj(id){ MyObj obj = getObjById(id); if (obj == null) { throw n
我的代码如下。可能我以类似的方式多次使用它,即简单地说,我正在以这种方式管理 session 和事务: List users= null; try{ sess
在开发J2EE Web应用程序时,我通常会按以下方式组织我的包结构 com.jameselsey.. 控制器-控制器/操作转到此处 服务-事务服务类,由控制器调用 域-应用程序使用的我的域类/对象 D
这更多是出于好奇而不是任何重要问题,但我只是想知道 memmove 中的以下片段文档: Copying takes place as if an intermediate buffer were us
路径压缩涉及将根指定为路径上每个节点的新父节点——这可能会降低根的等级,并可能降低路径上所有节点的等级。有办法解决这个问题吗?有必要处理这个吗?或者,也许可以将等级视为树高的上限而不是确切的高度? 谢
我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受一个指向类型 B 的类的指针。当函数调用另一个函数时,我
有没有办法让 valgrind 使用多个处理器? 我正在使用 valgrind 的 callgrind 进行一些瓶颈分析,并注意到我的应用程序中的资源使用行为与在 valgrind/callgrind
假设我们要使用 ReaderT [(a,b)]超过 Maybe monad,然后我们想在列表中进行查找。 现在,一个简单且不常见的方法是: 第一种可能性 find a = ReaderT (looku
我的代码似乎有问题。我需要说的是: if ( $('html').attr('lang').val() == 'fr-FR' ) { // do this } else { // do
根据this文章(2018 年 4 月)AKS 在可用性集中运行时能够跨故障域智能放置 Pod,但尚不考虑更新域。很快就会使用更新域将 Pod 放入 AKS 中吗? 最佳答案 当您设置集群时,它已经自
course | section | type comart2 : bsit201 : lec comart2 :
我正在开发自己的 SDK,而这又依赖于某些第 3 方 SDK。例如 - OkHttp。 我应该将 OkHttp 添加到我的 build.gradle 中,还是让我的 SDK 用户包含它?在这种情况下,
随着 Rust 越来越充实,我对它的兴趣开始激起。我喜欢它支持代数数据类型,尤其是那些匹配的事实,但是对其他功能习语有什么想法吗? 例如标准库中是否有标准过滤器/映射/归约函数的集合,更重要的是,您能
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
我一直在研究 PHP 中的对象。我见过的所有示例甚至在它们自己的对象上都使用了对象构造函数。 PHP 会强制您这样做吗?如果是,为什么? 例如: firstname = $firstname;
...比关联数组? 关联数组会占用更多内存吗? $arr = array(1, 1, 1); $arr[10] = 1; $arr[] = 1; // <- index is 11; does the
我是一名优秀的程序员,十分优秀!