Ios 我怎样才能在图像中找到最亮的点(可能是金属)?
我用金属制作了一个定制的内核。这很有用,因为它接近实时。我正在避免任何可能会实时延迟的cgcontext或cicontext。我的内核基本上做了Hough变换,但我似乎不知道如何从图像缓冲区读取白点 下面是kernel.metal:Ios 我怎样才能在图像中找到最亮的点(可能是金属)?,ios,metal,core-image,metal-performance-shaders,Ios,Metal,Core Image,Metal Performance Shaders,我用金属制作了一个定制的内核。这很有用,因为它接近实时。我正在避免任何可能会实时延迟的cgcontext或cicontext。我的内核基本上做了Hough变换,但我似乎不知道如何从图像缓冲区读取白点 下面是kernel.metal: #include <CoreImage/CoreImage.h> extern "C" { namespace coreimage { float4 hough(sampler src) { // M
#include <CoreImage/CoreImage.h>
extern "C" {
namespace coreimage {
float4 hough(sampler src) {
// Math
// More Math
// eventually:
if (luminance > 0.8) {
uint2 position = src.coord()
// Somehow add this to an array because I need to know the x,y pair
}
return float4(luminance, luminance, luminance, 1.0);
}
}
}
这不会给出亮度大于0.8的每个像素,但对于我来说,它返回的足够多:每列中的最高值及其位置
优点:只将(2*图像宽度)字节复制到CPU,而不是每个像素,可以节省大量时间(几毫秒)
缺点:如果你在同一列中有两个主要的白点,你永远不会知道。如果这符合您的用例,您可能必须修改它并按行而不是按列进行计算
跟进:
呈现输出时似乎有问题。以金属形式返回的浮点值与我在swift中获得的UInt8值不相关
描述问题
编辑:提供了非常方便的金属功能。当您对金属值(例如0.5)调用它并返回它时,您将在CPU上获得正确的值(例如128)。查看
类别还原中的过滤器(如)。它们返回的图像只有几个像素高,包含缩小结果。但是您仍然需要渲染它们才能读取Swift函数中的值
使用这种方法解决问题的问题是,您不知道事先返回的坐标数。不过,当核心映像调用内核时,它需要知道输出的扩展。你可以假设一个静态的最大坐标数,但这听起来很乏味
我认为您最好使用在CPU上迭代图像像素(并行化,超级高效)以找到相应的坐标
你可以做一个混合的方法,在GPU上用核心图像做每像素重的数学运算,然后在CPU上用Accelerate做分析。您甚至可以使用集成处理器将CPU部件集成到核心映像管道中。谢谢!我尝试过Accelerate和CiImageProcessornel,这涉及到将像素复制到内存中,这使我的相机速度下降到了11fps左右(我的目标是至少30帧)。我很好奇CICategoryReduction的底层内核是什么样子的。不确定内置是否适合我的需要,但我可能可以做一个。因为GPU和CPU内存在iOS中共享,所以不需要复制数据。从ciimageprocessornel
的CIImageProcessorInput
中,您可以获取输入图像的底层数据缓冲区的基址
,并直接使用Accelerate对其进行操作。您能再解释一下如何读取CPU中的字节吗?我用的是.getBytes()
,速度慢了很多。在文档中,“核心映像将网络中的过滤器连接成尽可能少的内核,避免创建中间缓冲区。但是,它无法使用映像处理器内核实现这一点。”我认为这也可能是一个问题。考虑到这一点,我想你也不能真正使用ciimageprocessornel
,因为你不知道结果的数量。不知何故,您需要将最终的CIImage
渲染到您可以使用Accelerate访问的一些数据缓冲区中(例如使用CIContext.render(CIImage,toBitmap:UnsafeMutableRawPointer,rowBytes:Int,bounds:CGRect,format:CIFormat,colorSpace:CGColorSpace?
)。你可以说你的图像最初从哪里来,你需要结果到哪里去(例如,如果需要进一步的处理)?你对srgba到线性有什么见解,因为我读取的值与我的内核返回的值不同吗
/// Returns the maximum value in each column.
///
/// - Parameter src: a sampler for the input texture
/// - Returns: maximum value in for column
float4 maxValueForColumn(sampler src) {
const float2 size = float2(src.extent().z, src.extent().w);
/// Destination pixel coordinate, normalized
const float2 pos = src.coord();
float maxV = 0;
for (float y = 0; y < size.y; y++) {
float v = src.sample(float2(pos.x, y / size.y)).x;
if (v > maxV) {
maxV = v;
}
}
return float4(maxV, maxV, maxV, 1.0);
}
/// Returns the normalized coordinate of the maximum value in each column.
///
/// - Parameter src: a sampler for the input texture
/// - Returns: normalized y-coordinate of the maximum value in for column
float4 maxCoordForColumn(sampler src) {
const float2 size = float2(src.extent().z, src.extent().w);
/// Destination pixel coordinate, normalized
const float2 pos = src.coord();
float maxV = 0;
float maxY = 0;
for (float y = 0; y < size.y; y++) {
float v = src.sample(float2(pos.x, y / size.y)).x;
if (v > maxV) {
maxY = y / size.y;
maxV = v;
}
}
return float4(maxY, maxY, maxY, 1.0);
}