【发布时间】:2020-10-28 21:35:53
【问题描述】:
以下代码的错误是,它只能部分找到第一张图像本身。
让我更清楚一点,我截取了一张图片,将其裁剪并放在桌面上。然后我将实际的原始图像也以全尺寸(未裁剪)保存在桌面上。
当我运行代码时,它会正确检测到桌面上裁剪图像的所有坐标,但是,当我打开全尺寸图像并将其悬停时,它不会检测到任何东西并返回 null,而它应该是也能够检测全尺寸图像内的像素位置。
我将发布一个视频来说明我的意思,以便更清楚:
https://www.youtube.com/watch?v=Ha3eGxWcAF8
如您所见,它不会检测主图像上的像素。 那里有什么问题?
为什么它只检测加载的裁剪图像,而不是根据实际的全尺寸图像检测屏幕截图上的位置?
代码如下:
public static Point? Find(Bitmap first, Bitmap second)
{
if (null == first || null == second)
{
return null;
}
if (first.Width < second.Width || first.Height < second.Height)
{
return null;
}
var firstArray = GetPixelArray(first);
var secondArray = GetPixelArray(second);
foreach (var firstLineMatchPoint in FindMatch(firstArray.Take(first.Height - second.Height), secondArray[0]))
{
if (IssecondPresentAtLocation(firstArray, secondArray, firstLineMatchPoint, 1))
{
return firstLineMatchPoint;
}
}
return null;
}
private static int[][] GetPixelArray(Bitmap bitmap)
{
var result = new int[bitmap.Height][];
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
for (int y = 0; y < bitmap.Height; ++y)
{
result[y] = new int[bitmap.Width];
Marshal.Copy(bitmapData.Scan0 + y * bitmapData.Stride, result[y], 0, result[y].Length);
}
bitmap.UnlockBits(bitmapData);
return result;
}
private static IEnumerable<Point> FindMatch(IEnumerable<int[]> firstLines, int[] secondLine)
{
var y = 0;
foreach (var firstLine in firstLines)
{
for (int x = 0, n = firstLine.Length - secondLine.Length; x < n; ++x)
{
if (ContainSameElements(firstLine, x, secondLine, 0, secondLine.Length))
{
yield return new Point(x, y);
}
}
y += 1;
}
}
private static bool ContainSameElements(int[] first, int firstStart, int[] second, int secondStart, int length)
{
for (int i = 0; i < length; ++i)
{
if (first[i + firstStart] != second[i + secondStart])
{
return false;
}
}
return true;
}
private static bool IssecondPresentAtLocation(int[][] first, int[][] second, Point point, int alreadyVerified)
{
//we already know that "alreadyVerified" lines already match, so skip them
for (int y = alreadyVerified; y < second.Length; ++y)
{
if (!ContainSameElements(first[y + point.Y], point.X, second[y], 0, second.Length))
{
return false;
}
}
return true;
}
static void Main(string[] args)
{
int counter = 1;
while (true)
{
Console.WriteLine("Executing pixel search");
Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
Bitmap bitmap2 = (Bitmap)Image.FromFile(@"path_to_desktop\cropped.jpg", true);
if (Find(bitmap, bitmap2) == null)
{
Console.WriteLine("Not found.");
}
else {
Console.WriteLine($"{Find(bitmap, bitmap2)}.");
}
System.Threading.Thread.Sleep(500); // loop to detect new position
counter++;
}
}
【问题讨论】:
-
您使用的是 .Net Framework 还是 .Net Core?这些图片可以分享吗?
-
.NET core,至于图片我还不太明白你的意思。它基本上在另一个图像中搜索图像/像素,所以任何都可以工作
-
当您保存文件时,您是否使用正确的图像类型扩展名保存?
-
@jdweng 是的,否则它只会返回文件不存在打开它
标签: c# image-processing search pixel