C# 如何实现位图的最小分配搜索?
首先,我的问题是,找出新的方法来实现快速高效的图像搜索,试图让它超过0.65~0.80毫秒的时间 到目前为止,我已经通过使用并行不安全位图解析、在初始索引后对部分进行排序以及许多其他简化,对搜索进行了广泛的改进。但让我感到困惑的是一种不使用中介来存储和比较数据的方法,额外的好处还包括对搜索到的位图进行最小解析(即对目标进行解析搜索) 既然有了这个算法,我们能做些什么来改进它呢C# 如何实现位图的最小分配搜索?,c#,in-memory,C#,In Memory,首先,我的问题是,找出新的方法来实现快速高效的图像搜索,试图让它超过0.65~0.80毫秒的时间 到目前为止,我已经通过使用并行不安全位图解析、在初始索引后对部分进行排序以及许多其他简化,对搜索进行了广泛的改进。但让我感到困惑的是一种不使用中介来存储和比较数据的方法,额外的好处还包括对搜索到的位图进行最小解析(即对目标进行解析搜索) 既然有了这个算法,我们能做些什么来改进它呢 [MethodImpl(MethodImplOptions.AggressiveInlining)] p
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static Point InMemSearch(Bitmap Haystack, Bitmap NeedleStack)
{
if (NeedleStack == null)
throw new System.ArgumentNullException(nameof(NeedleStack));
if (Haystack == null)
{
return default;
}
BitmapData Stack = Haystack.LockBits(new Rectangle(0, 0, Haystack.Width, Haystack.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);
BitmapData Needle = NeedleStack.LockBits(new Rectangle(0, 0, NeedleStack.Width, NeedleStack.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);
Point p = default;
byte* PtrStackPixel = (byte*)Stack.Scan0;
byte* PtrNeedlePixel = (byte*)Needle.Scan0;
Dictionary<int, IEnumerable<byte>> NeedleLookup = new Dictionary<int, IEnumerable<byte>>();
Dictionary<int, IEnumerable<byte>> StackLookup = new Dictionary<int, IEnumerable<byte>>();
IEnumerable<byte> GetNeedleLine(int needleY)
{
if(NeedleLookup.ContainsKey(needleY))
{
return NeedleLookup[needleY];
}
var NeedleLine = new byte[Needle.Width];
for (int x = 0; x < Needle.Width; x++)
{
byte np = *(PtrNeedlePixel + (needleY * Needle.Stride) + (x >> 3));
np &= (byte)(0x80 >> (x & 0x7));
NeedleLine[x] = np;
}
NeedleLookup.Add(needleY, NeedleLine);
return NeedleLine;
}
IEnumerable<byte> GetStackLine(int stackY)
{
if(StackLookup.ContainsKey(stackY))
{
return StackLookup[stackY];
}
var StackLine = new byte[Stack.Width];
for (var x = 0; x < Stack.Width; x++)
{
byte sp = *(PtrStackPixel + (stackY * Stack.Stride) + (x >> 3));
sp &= (byte)(0x80 >> (x & 0x7));
StackLine[x] = sp;
}
StackLookup[stackY] = StackLine;
return StackLine;
}
int Bad = 0;
while(!GetNeedleLine(0 + Bad).Any(b => b > 0))
{
Bad++;
}
int BadStackLines = 0;
int GoodIndex = 0;
while (GoodIndex <= 0)
{
GoodIndex = SubListIndex(GetStackLine(Stack.Height - BadStackLines), 0, GetNeedleLine(0 + Bad));
if (GoodIndex == -1)
{
BadStackLines++;
}
else
{
if (GetStackLine(Stack.Height - BadStackLines - 1).Skip(GoodIndex).Take(Needle.Width).SequenceEqual(GetNeedleLine(0 + Bad - 1)))
{
p = new Point(GoodIndex, Stack.Height - BadStackLines);
}
else
{
GoodIndex = 0;
}
}
}
Haystack.UnlockBits(Stack);
NeedleStack.UnlockBits(Needle);
return p;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SubListIndex<T>(IEnumerable<T> list, int start, IEnumerable<T> sublist)
{
int Index = 0;
var LoopResult = Parallel.For(start, list.Count() - sublist.Count() + 1, (listIndex, loopState) =>
{
int count = 0;
while (count < sublist.Count() && sublist.ElementAt(count).Equals(list.ElementAt(listIndex + count)))
{
count++;
}
if (count == sublist.Count())
{
Index = listIndex;
loopState.Break();
}
});
if (LoopResult.IsCompleted)
{
return -1;
}
else
{
return Index;
}
}
[MethodImpl(MethodImplOptions.AggressiveInline)]
MemSearch中的公共不安全静态点(位图草堆、位图针堆)
{
if(NeedleStack==null)
抛出新的System.ArgumentNullException(nameof(NeedleStack));
if(Haystack==null)
{
返回默认值;
}
BitmapData Stack=Haystack.LockBits(新矩形(0,0,Haystack.Width,Haystack.Height),ImageLockMode.ReadOnly,PixelFormat.Format1BPindexed);
BitmapData Pineder=NeedleStack.LockBits(新矩形(0,0,NeedleStack.Width,NeedleStack.Height),ImageLockMode.ReadOnly,PixelFormat.Format1BPindexed);
p点=默认值;
字节*PtrStackPixel=(字节*)Stack.Scan0;
字节*PtrNeedlePixel=(字节*)Needle.Scan0;
Dictionary NeedleLookup=新建字典();
Dictionary StackLookup=新建字典();
IEnumerable GetNeedline(无针)
{
if(needleokup.ContainsKey(needleY))
{
返回NeedleLookup[needrey];
}
var-needline=新字节[指针宽度];
用于(int x=0;x>3));
np&=(字节)(0x80>>(x&0x7));
针线[x]=np;
}
NeedleLookup.Add(needey,NeedleLine);
回针线;
}
IEnumerable GetStackLine(int stackY)
{
if(StackLookup.ContainsKey(stackY))
{
返回StackLookup[stackY];
}
var StackLine=新字节[Stack.Width];
对于(var x=0;x>3));
sp&=(字节)(0x80>>(x&0x7));
StackLine[x]=sp;
}
StackLookup[stackY]=StackLine;
返回堆垛线;
}
int Bad=0;
而(!GetNeedleLine(0+坏).Any(b=>b>0))
{
坏++;
}
int BadStackLines=0;
int-GoodIndex=0;
while(GoodIndex)
{
整数计数=0;
而(count
这仍然有数据结构需要比较,需要改进,但它实现了想法的一部分。尝试创建一个可以从c#调用的Matlab dll。在做DSP时,Matlab函数比c要好得多。对我来说,这与其说是速度问题,不如说是实现了这个想法,把它包含在我用来解决其他问题的想法包中。:)如果速度不重要,那么在Matlab中处理DSP的功能仍然更多,在C语言中。另一个选择是C++。如果使用C++/CLI,仍然可以与.NET代码的其余部分交互。C#当然可以完成所有这些低级的丑陋,但它并没有真正针对它进行优化。另一方面,尝试.NET内核和
Vector
操作,而不是通过线程和低级数组摸索实现并行(显然,这可能需要大量重写)。即使Span
也能帮上忙。谢谢你,但我会放弃,并继续尝试用我喜欢使用的工具找出最好的方法。我更新了我的代码,为其他人提供了我的第一种工作方法。