- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个包含多种图像类型(RGB、灰色...)的 C++ 应用程序,每种类型都具有旋转或缩放等属性。每种图像类型都是通过其他类型的一些计算生成的。例如,旋转的 GrayImage
是通过旋转 GrayImage
生成的,而 GrayImage
又是通过“灰色化” RGBImage
生成的。
我想用 GetX(...)
方法设计一个缓存类来缓存各种图像(可能还有计算路径中的所有图像)。此类还知道如何生成每个图像,以防它不在缓存中。
类必须满足一些约束:
由于我们处理的是不同类型和表现形式(RGB、GrayScale 等)的图像,因此缓存必须返回一个具体类,以便调用代码能够在不进行某种转换的情况下使用它。因此,缓存机制必须包含包含具体类型的不同缓存结构。 (如果我在这里错了,请修复我)
map<...,RGBImage>
map<...,GrayImage>
例如。
缓存必须能够灵活应对图像计算的变化。只要不是太大,代码更改是可以接受的。
我的当前版本为每种图像类型附加了一个 Key
结构。有GrayKey
、RGBKey
等。各种键包含 Scale 和 Rotation 等属性,并且可以具有特定于图像的属性(例如 GrayKey
的 toGrayConvertingMethod)。缓存包含以下形式的 map :
map <XKey,XImage>
GetX(...)
方法接收一个 Key
结构作为请求旋转 GrayImage 的参数。但是,此实现会强制缓存应用大量逻辑来计算图像。它必须检查 GrayKey 是否请求旋转图像并采取相应行动。我想以更优雅的方式“编码”这种图像计算关系,但似乎找不到。
有什么建议吗?
非常感谢。
最佳答案
也许您可以使用 Boost.MultiIndex
做一些事情容器?它可以让你创建一个类型来存储图像数据,以及它是如何被操作的细节,然后根据你想要的任何键组合查找值。如果您以前没有使用过它,它可能看起来有点令人生畏,但我在下面附上了一个示例。
显然,我的例子只处理缓存机制的存储/检索部分,如果你把它粘在一起,如果查找失败,它可以生成图像,它应该做你想做的一切。扩展它也很容易……需要查找额外的参数吗?您只需要将另一个索引添加到 ImageCache
typedef。
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/tag.hpp>
#include <boost/shared_array.hpp>
#include <algorithm>
#include <iostream>
#include <utility>
// A cache item, stores the image data, and any values we need to
// index on.
struct ImageCacheItem
{
enum RgbMode { RGB_MODE_COLOUR, RGB_MODE_GREYSCALE };
// Im not sure how much copying goes on in the container,
// so using a smart pointer to prevent copying large amounts
// of data.
boost::shared_array<char> imageBuffer;
double rotation;
double scale;
RgbMode rgbMode;
ImageCacheItem(double r, double s)
: rotation(r), scale(s)
{
}
};
// These are "tag" structures, they are used as part of the
// multi_index_container as a way to distinguish between indicies.
struct ByRotation {};
struct ByScale {};
struct ByRgb {};
struct ByRotationScale {};
// Typedef of the container itself.
typedef boost::multi_index_container<
ImageCacheItem, // The data type for the container.
// Note there is no "key" type, as the key values
// are extracted from the data items theselves.
boost::multi_index::indexed_by<
// Define an index for the rotation value
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<ByRotation>,
BOOST_MULTI_INDEX_MEMBER(ImageCacheItem, double, rotation)
>,
// Define an index for the scale value
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<ByScale>,
BOOST_MULTI_INDEX_MEMBER(ImageCacheItem, double, scale)
>,
// Define an index for the rgb value
boost::multi_index::hashed_non_unique<
boost::multi_index::tag<ByRgb>,
BOOST_MULTI_INDEX_MEMBER(ImageCacheItem, ImageCacheItem::RgbMode, rgbMode)
>,
// Define an index by rotation + scale
boost::multi_index::hashed_unique<
boost::multi_index::tag<ByRotationScale>,
boost::multi_index::composite_key<
ImageCacheItem,
BOOST_MULTI_INDEX_MEMBER(ImageCacheItem, double, rotation),
BOOST_MULTI_INDEX_MEMBER(ImageCacheItem, double, scale)
>
>
>
> ImageCache;
// Utility typedefs, you'll want these to shorten the iterator
// data types when you're looking things up (see main).
typedef ImageCache::index<ByRotation>::type ImageCacheByRotation;
typedef ImageCache::index<ByScale>::type ImageCacheByScale;
typedef ImageCache::index<ByRgb>::type ImageCacheByRgb;
typedef ImageCache::index<ByRotationScale>::type ImageCacheByRotationScale;
int main()
{
// Create the cache and add time "images" to it.
ImageCache cache;
cache.insert(ImageCacheItem(10, 10));
cache.insert(ImageCacheItem(10, 20));
cache.insert(ImageCacheItem(20, 20));
// look up the images with scale of 20.
typedef ImageCacheByScale::iterator ScaleIter;
std::pair<ScaleIter, ScaleIter> scaleResult = cache.get<ByScale>().equal_range(20);
std::cout << "Found " << std::distance(scaleResult.first, scaleResult.second) << " Results" << std::endl;
// look up the image with rotation = 10 && scale = 20.
ImageCacheByRotationScale::iterator rsResult = cache.get<ByRotationScale>().find(boost::make_tuple(10, 20));
std::cout << "Found " << (rsResult != cache.get<ByRotationScale>().end() ? 1 : 0) << " Results" << std::endl;
return 0;
}
编辑:它很大...
我试过扩展上面的示例以在缓存中找到与您搜索的内容最接近但有偏差的图像,所以如果您想要旋转 45,并且比例为 10,如果没有找到完全匹配,它会倾向于一个属性相同而另一个属性为 0 的结果(即比例为 10,但旋转为 0,因此您需要做的就是旋转) .
代码被注释以解释其作用,但基本上,它使用模板递归按顺序搜索索引,一旦索引找到一些匹配项,它就会尝试按相关性顺序对它们进行排序,并返回最佳匹配。要添加另一个属性,您需要执行以下操作:
ImageCacheItem
ImageCacheSimilarity
ImageCache
typedef它可能不是最佳解决方案,但我认为它涵盖了您在评论中提到的用例。
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/tag.hpp>
#include <boost/mpl/list.hpp>
#include <boost/optional.hpp>
#include <boost/ref.hpp>
#include <boost/shared_array.hpp>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <utility>
#include <vector>
#include <typeinfo>
// A cache item, stores the image data, and any values we need to
// index on.
struct ImageCacheItem
{
enum RgbMode { RGB_MODE_COLOUR, RGB_MODE_GREYSCALE };
// Im not sure how much copying goes on in the container,
// so using a smart pointer to prevent copying large amounts
// of data.
boost::shared_array<char> imageBuffer;
double rotation;
double scale;
RgbMode rgbMode;
ImageCacheItem(double r, double s)
: rotation(r), scale(s)
{
}
};
// Calculates the similarity between two ImageCacheItem objects.
int ImageCacheSimilarity(const ImageCacheItem& item, const ImageCacheItem& target)
{
const double EPSILON = 0.0000001;
int score = 0;
// 2 points for an exact match
// 1 point if the value is 0 (e.g. not rotated, so can be used as a starting point)
// -1 point otherwise
score += (std::fabs(item.rotation - target.rotation) < EPSILON)
? 2
: ((std::fabs(item.rotation) < EPSILON) ? 1 : -1);
score += (std::fabs(item.scale - target.scale) < EPSILON)
? 2
: ((std::fabs(item.scale) < EPSILON) ? 1 : -1);
score += (item.rgbMode == target.rgbMode) ? 2 : 0;
return score;
}
// Orders ImageCacheItem objects based on their similarity to a target value.
struct ImageCacheCmp
{
const ImageCacheItem& target;
ImageCacheCmp(const ImageCacheItem& t)
: target(t)
{
}
bool operator()(const ImageCacheItem& a, const ImageCacheItem& b)
{
return (ImageCacheSimilarity(a, target) > ImageCacheSimilarity(b, target));
}
};
// These are "tag" structures, they are used as part of the
// multi_index_container as a way to distinguish between indicies.
struct ByRotation {};
struct ByScale {};
struct ByRgb {};
struct ByRotationScale {};
// Typedef of the container itself.
typedef boost::multi_index_container<
ImageCacheItem, // The data type for the container.
// Note there is no "key" type, as the key values
// are extracted from the data items theselves.
boost::multi_index::indexed_by<
// The order of indicies here will affect performance, put the
// ones that match against the most fields first. Its not required
// to make it work, but it will reduce the number of matches to
// compare against later on.
// Define an index by rotation + scale
boost::multi_index::hashed_unique<
boost::multi_index::tag<ByRotationScale>,
boost::multi_index::composite_key<
ImageCacheItem,
BOOST_MULTI_INDEX_MEMBER(ImageCacheItem, double, rotation),
BOOST_MULTI_INDEX_MEMBER(ImageCacheItem, double, scale)
>
>,
// Define an index for the rotation value
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<ByRotation>,
BOOST_MULTI_INDEX_MEMBER(ImageCacheItem, double, rotation)
>,
// Define an index for the scale value
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<ByScale>,
BOOST_MULTI_INDEX_MEMBER(ImageCacheItem, double, scale)
>,
// Define an index for the rgb value
boost::multi_index::hashed_non_unique<
boost::multi_index::tag<ByRgb>,
BOOST_MULTI_INDEX_MEMBER(ImageCacheItem, ImageCacheItem::RgbMode, rgbMode)
>
>
> ImageCache;
// Type of the vector used when collecting index results. It stores
// references to the values in the cache to minimise copying.
typedef std::vector<boost::reference_wrapper<const ImageCacheItem> > ImageCacheResults;
// Utility class for overload resolution
template <int I>
struct Int2Type
{
enum { value = I };
};
void FindMatches(
const ImageCacheItem& item,
const ImageCache& cache,
ImageCacheResults& results,
const Int2Type<boost::mpl::size<ImageCache::index_type_list>::type::value>&)
{
// End of template recursion
}
template <int I>
void FindMatches(
const ImageCacheItem& item,
const ImageCache& cache,
ImageCacheResults& results,
const Int2Type<I>&)
{
// Get the index being searched
typedef typename ImageCache::nth_index<I>::type Index;
// This type knows how to extract the relevant bits of ImageCacheItem
// for this particular index.
typename Index::key_from_value keyExtractor;
// Look for matches in the index.
std::pair<typename Index::const_iterator, typename Index::const_iterator> iter =
cache.get<I>().equal_range(keyExtractor(item));
// If we found any results, add them to 'results', otherwise
// continue to the next index.
if (iter.first != iter.second)
{
results.reserve(std::distance(iter.first, iter.second));
for ( ; iter.first != iter.second; ++iter.first)
{
results.push_back(boost::cref(*iter.first));
}
}
else
{
FindMatches(item, cache, results, Int2Type<I + 1>());
}
}
boost::optional<ImageCacheItem> FindClosestImage(const ImageCacheItem& item, const ImageCache& cache)
{
// Find exact/partial matches according to the indicies.
ImageCacheResults results;
FindMatches(item, cache, results, Int2Type<0>());
// If no matches were found, return an empty value
if (results.empty())
{
return boost::optional<ImageCacheItem>();
}
// We got this far, so we must have some candiates, the problem is
// we dont know which is the best match, so here we sort the results
// based on proximity to the "item". However, we are only interested
// in the best match, so do a partial_sort.
std::partial_sort(results.begin(), results.begin() + 1, results.end(), ImageCacheCmp(item));
return results.front().get();
}
int main()
{
// Create the cache and add some "images" to it.
ImageCache cache;
cache.insert(ImageCacheItem(10, 20));
cache.insert(ImageCacheItem(10, 10));
cache.insert(ImageCacheItem(10, 2));
cache.insert(ImageCacheItem(20, 20));
cache.insert(ImageCacheItem(30, 20));
cache.insert(ImageCacheItem(30, 0));
// Look for an image similar to rotation = 30 && scale = 2.
boost::optional<ImageCacheItem> result = FindClosestImage(ImageCacheItem(30, 2), cache);
// Have to check if result is value before usage, it would be empty
// if not match is found.
if (result)
{
std::cout << "Found (" << result->rotation
<< ", " << result->scale << ")"
<< std::endl;
}
else
{
std::cout << "No Results" << std::endl;
}
return 0;
}
关于C++ 缓存设计建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6389481/
我阅读了有关 JSR 107 缓存 (JCache) 的内容。 我很困惑:据我所知,每个 CPU 都管理其缓存内存(无需操作系统的任何帮助)。 那么,为什么我们需要 Java 缓存处理程序? (如果C
好吧,我是 jQuery 的新手。我一直在这里和那里搞乱一点点并习惯它。我终于明白了(它并不像某些人想象的那么难)。因此,鉴于此链接:http://jqueryui.com/sortable/#dis
我正在使用 Struts 2 和 Hibernate。我有一个简单的表,其中包含一个日期字段,用于存储有关何时发生特定操作的信息。这个日期值显示在我的 jsp 中。 我遇到的问题是hibernate更
我有点不确定这里发生了什么,但是我试图解释正在发生的事情,也许一旦我弄清楚我到底在问什么,就可能写一个更好的问题。 我刚刚安装了Varnish,对于我的请求时间来说似乎很棒。这是一个Magneto 2
解决 Project Euler 的问题后,我在论坛中发现了以下 Haskell 代码: fillRow115 minLength = cache where cache = ((map fill
我正试图找到一种方法来为我网络上的每台计算机缓存或存储某些 python 包。我看过以下解决方案: pypicache但它不再被积极开发,作者推荐 devpi,请参见此处:https://bitbuc
我想到的一个问题是可以从一开始就缓存网络套接字吗?在我的拓扑中,我在通过双 ISP 连接连接到互联网的 HAProxy 服务器后面有 2 个 Apache 服务器(带有 Google PageSpee
我很难说出不同缓存区域 (OS) 之间的区别。我想简要解释一下磁盘\缓冲区\交换\页面缓存。他们住在哪里?它们之间的主要区别是什么? 据我了解,页面缓存是主内存的一部分,用于存储从 I/O 设备获取的
1.题目 请你为最不经常使用(LFU)缓存算法设计并实现数据结构。 实现 LFUCache 类: LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象 in
1.题目 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: ① LRUCache(int capacity) 以正整数作为容量 capacity
我想在访问该 View 时关闭某些页面的缓存。它适用于简单查询模型对象的页面。 好像什么时候 'django.middleware.cache.FetchFromCacheMiddleware', 启
documents为 ExePackage element state Cache属性的目的是 Whether to cache the package. The default is "yes".
我知道 docker 用图层存储每个图像。如果我在一台开发服务器上有多个用户,并且每个人都在运行相同的 Dockerfile,但将镜像存储为 user1_myapp . user2 将其存储为 use
在 Codeigniter 中没有出现缓存问题几年后,我发现了一个问题。我在其他地方看到过该问题,但没有适合我的解决方案。 例如,如果我在 View 中更改一些纯 html 文本并上传新文件并按 F5
我在 Janusgraph 文档中阅读了有关 Janusgraph Cache 的内容。关于事务缓存,我几乎没有怀疑。我在我的应用程序中使用嵌入式 janusgrah 服务器。 如果我只对例如进行读取
我想知道是否有来自终端的任何命令可以用来匹配 Android Studio 中执行文件>使缓存无效/重新启动的使用。 谢谢! 最佳答案 According to a JetBrains employe
我想制作一个 python 装饰器来内存函数。例如,如果 @memoization_decorator def add(a, b, negative=False): print "Com
我经常在 jQuery 事件处理程序中使用 $(this) 并且从不缓存它。如果我愿意的话 var $this = $(this); 并且将使用变量而不是构造函数,我的代码会获得任何显着的额外性能吗?
是的,我要说实话,我不知道varnish vcl,我可以解决一些基本问题,但是我不太清楚,这就是为什么我遇到问题了。 我正在尝试通过http请求设置缓存禁止,但是该请求不能通过DNS而是通过 Varn
在 WP 站点上加载约 4000 个并发用户时遇到此问题。 这是我的配置: F5 负载均衡器 ---> Varnish 4,8 核,32 Gb RAM ---> 9 个后端,4 个核,每个 16 RA
我是一名优秀的程序员,十分优秀!