我想在图像(干草堆)中找到一个图像(针).
为了简单起见,我拍了两张桌面截图.一个全尺寸(干草堆)和一个小尺寸(针).然后我循环通过干草堆图像并尝试找到针图像.
预期结果:在正确的位置找到针图像.
我已经让它适用于某些坐标/宽度/高度(A).
但有时比特似乎"关闭",因此找不到匹配(B).
我能做错什么?欢迎任何建议.谢谢.
var needle_height = 25;
var needle_width = 25;
var haystack_height = 400;
var haystack_width = 500;
Run Code Online (Sandbox Code Playgroud)
A.示例输入 - 匹配
var needle = screenshot(5, 3, needle_width, needle_height);
var haystack = screenshot(0, 0, haystack_width, haystack_height);
var result = findmatch(haystack, needle);
Run Code Online (Sandbox Code Playgroud)
B.示例输入 - 不匹配
var needle = screenshot(5, 5, needle_width, needle_height);
var haystack = screenshot(0, 0, haystack_width, haystack_height);
var result = findmatch(haystack, …Run Code Online (Sandbox Code Playgroud) 我正在研究摄像机拍摄的1000万像素图像.
目的是在矩阵(二维阵列)中记录每个像素的灰度值.
我第一次使用GetPixel,但它需要25秒才能完成.现在我使用Lockbits但是它需要10秒,如果我不将结果保存在文本文件中则需要3秒.
我的导师说他们不需要注册结果,但3秒仍然太慢.我在我的程序中做错了什么,或者我的应用程序有比Lockbits更快的东西吗?
这是我的代码:
public void ExtractMatrix()
{
Bitmap bmpPicture = new Bitmap(nameNumber + ".bmp");
int[,] GRAY = new int[3840, 2748]; //Matrix with "grayscales" in INTeger values
unsafe
{
//create an empty bitmap the same size as original
Bitmap bmp = new Bitmap(bmpPicture.Width, bmpPicture.Height);
//lock the original bitmap in memory
BitmapData originalData = bmpPicture.LockBits(
new Rectangle(0, 0, bmpPicture.Width, bmpPicture.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
//lock the new bitmap in memory
BitmapData newData = bmp.LockBits(
new Rectangle(0, 0, bmpPicture.Width, bmpPicture.Height),
ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
//set …Run Code Online (Sandbox Code Playgroud) 我想我已经找到了一种更快的方法来复制c#中的位图.(如果它有效,我确定我不是第一个,但我还没有在任何地方见过它.)
我能想到的最简单的方法是断言我的想法是基于什么,如果没有人在其中发现漏洞,假设这个想法是合理的:
void FastCopyRegion(Bitmap CopyMe, ref Bitmap IntoMe, Rectangle CopyArea)
{
//`IntoMe` need not be declared `ref` but it brings
// attention to the fact it will be modified
Debug.Assert(CopyMe.PixelFormat == IntoMe.PixelFormat,
"PixelFormat mismatch, we could have a problem");
Debug.Assert(CopyMe.Width == IntoMe.Width, //This check does not verify
"Stride mismatch, we could have a problem");// sign of `stride` match
BitmapData copyData = CopyMe.LockBits(CopyArea,
ImageLockMode.ReadWrite, CopyMe.PixelFormat);
IntoMe.UnlockBits(copyData);
}
Run Code Online (Sandbox Code Playgroud)
1)LockBits简单地将一块像素数据从位图复制到固定存储器中进行编辑并在使用中复制回来UnlockBits
2)使用LockBits不会影响复制的内存块,因此它应该对从中复制的图像没有影响.
3)由于您从不输入unsafe代码,因此不应存在损坏内存的风险.
我看到可能的漏洞:
1)如果PixelFormat两个位图的s不同,则此方法可能无法始终正确复制.但是,由于 …
从解锁的Bitmap非托管内存直接写入和读取是否可以?
在我解锁Bitmap后,我可以继续使用BitmapData吗?我做了一个测试应用程序,我可以在鼠标位置读取PictureBox的Bitmap像素,而另一个线程正在将像素写入同一个Bitmap.
编辑1:正如Boing他在回答中指出的那样:"Scan0没有指向Bitmap对象的实际像素数据;而是指向一个临时缓冲区,它代表Bitmap对象中像素数据的一部分." 来自MSDN.
但是一旦我得到了Scan0,我就可以读取/写入Bitmap而无需Lockbits或UnlockBits!我在一个帖子里做了很多次.相对于MSDN,它不应该发生,因为Scan0指向位图数据的COPY!好吧,在C#中,所有测试表明它不是副本.在C++中,我不知道它是否正常工作.
编辑2:使用旋转方法有时会使操作系统释放位图像素数据副本.结论,it is not safe to read/write an unlocked Bitmap Scan0.谢谢Boing的回答和评论!
下面是我如何获取BitmapData并读取和写入像素值.
/// <summary>
/// Locks and unlocks the Bitmap to get the BitmapData.
/// </summary>
/// <param name="bmp">Bitmap</param>
/// <returns>BitmapData</returns>
public static BitmapData GetBitmapData(Bitmap bmp)
{
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
bmp.UnlockBits(bmpData);
return bmpData;
}
/// <summary>
/// Get pixel directly from unamanged pixel data based on the Scan0 pointer.
/// </summary> …Run Code Online (Sandbox Code Playgroud) 我最近使用锁定的位图,并且我一直"试图访问无效内存"错误.这主要是因为位图已在内存中移动.有些人GCHandle.Alloc()用来在CLR中分配内存并固定它.不Bitmap.LockBits()这样做?我不明白"锁定"内存和"固定"内存之间的区别.你能解释术语和差异吗?
我从这个链接(Mifare Ultralight C Lock)中获得了参考,使Mifare Ultralight标签上的所有页面都是只读的.
我可以在Android上成功在Mifare Ultralight标签上写一条消息.现在我要锁定第4到7页(或任何特定页面).以上链接仅显示如何锁定所有页面.我如何锁定特定页面?
此代码锁定所有页面:
mifare.transceive(new byte[] {
(byte)0xA2, /* CMD = WRITE */
(byte)0x02, /* PAGE = 2 */
(byte)0x00, (byte)0x00, (byte)0xFF, (byte)0xFF /* DATA = lock pages 3..15*/
});
Run Code Online (Sandbox Code Playgroud)
public static boolean writeOnMifareUltralight(Context _context, Tag tag,String pageData, int i) {
byte[]result;
MifareUltralight mifare = null;
try {
mifare = MifareUltralight.get(tag);
mifare.connect();
mifare.writePage(i, pageData.getBytes(Charset.forName("US-ASCII")));
mifare.transceive(new byte[] {
(byte)0xA2, /* CMD = WRITE */
(byte)0x02, /* PAGE = 2 */
(byte)0x00, (byte)0x00, (byte)0xFF, (byte)0xFF/* DATA …Run Code Online (Sandbox Code Playgroud) 所以,我对我刚刚跑过的快速测试非常困惑.我在C#中进行一些图像处理.Get/SetPixel()已被证明太慢,所以我使用LockBits来获取原始数据.
但是,我似乎遇到了一个我无法弄清楚的情况.在扫描图像时,似乎每个像素按照顺序布置为Bgra,即蓝色字节,绿色字节,红色字节和alpha.我的印象是他们将以Argb的顺序排列.这是我正在使用的代码示例.
BitmapData baseData =
m_baseImage.LockBits(new Rectangle(new Point(0, 0), m_baseImage.Size),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Bitmap test = new Bitmap(m_baseImage.Width, m_baseImage.Height);
byte* ptr = (byte*)baseData.Scan0;
for (int y = 0; y < m_baseImage.Height; ++y)
{
for (int x = 0; x < m_baseImage.Width; ++x)
{
// this works, image is copied correctly
Color c1 = Color.FromArgb(*(ptr + 3), *(ptr + 2), *(ptr + 1), *ptr);
// below does not work! Bytes are reversed.
//Color c1 = Color.FromArgb(*ptr, *(ptr + 1), *(ptr + 2), …Run Code Online (Sandbox Code Playgroud) 我设置了一个代码来随机覆盖2位不同颜色的位图,10次中有7次是蓝色,3次中有10次,颜色是绿色.然而,当它完成它看起来非常随机,就像它决定几次放7个蓝色像素,然后几次放3个绿色像素等等.
例:
我的代码是:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace FourEx
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(canvas.Image);
System.Drawing.Imaging.BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, 800, 600), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
unsafe
{
int tempy = 0;
while (tempy < 600)
{
byte* row = (byte*)bmpdata.Scan0 + (tempy * bmpdata.Stride);
for (int x = 0; …Run Code Online (Sandbox Code Playgroud) 我一直在研究C#中的边缘检测程序,为了让它运行得更快,我最近使用了锁定位.但是,lockBits仍然没有我想要的那么快.虽然问题可能是我的通用算法,但我也想知道是否有比我可以用于图像处理的lockBits更好的东西.
如果问题是算法,这是一个基本的解释.浏览一系列颜色(使用锁定位表示像素),并为每种颜色检查该像素周围的八个像素的颜色.如果这些像素与当前像素不够匹配,则将当前像素视为边缘.
这是定义像素是否为边的基本代码.它采用了九种颜色的Color [],第一种是要检查的像素.
public Boolean isEdgeOptimized(Color[] colors)
{
//colors[0] should be the checking pixel
Boolean returnBool = true;
float percentage = percentageInt; //the percentage used is set
//equal to the global variable percentageInt
if (isMatching(colors[0], colors[1], percentage) &&
isMatching(colors[0], colors[2], percentage) &&
isMatching(colors[0], colors[3], percentage) &&
isMatching(colors[0], colors[4], percentage) &&
isMatching(colors[0], colors[5], percentage) &&
isMatching(colors[0], colors[6], percentage) &&
isMatching(colors[0], colors[7], percentage) &&
isMatching(colors[0], colors[8], percentage))
{
returnBool = false;
}
return returnBool;
}
Run Code Online (Sandbox Code Playgroud)
此代码适用于每个像素,其颜色使用锁定位获取.
基本上,问题是,如何让我的程序运行得更快?这是我的算法,还是我可以使用比lockBits更快的东西?
顺便说,该项目是在GitHub上,在这里
我使用下面的代码从图像中提取RGB值,有时这是有效的,但是在某些文件上(看似Stride不能被位图的宽度整除)它返回混合值:
Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits(rect, Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format24bppRgb)
Dim ptr As IntPtr = bmpData.Scan0
Dim cols As New List(Of Color)
Dim bytes As Integer = Math.Abs(bmpData.Stride) * bmp.Height
Dim rgbValues(bytes - 1) As Byte
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes)
' Retrieve RGB values
For i = modByte To rgbValues.Length Step 3
cols.Add(Color.FromArgb(rgbValues(i + 2), rgbValues(i + 1), rgbValues(i)))
Next
bmp.UnlockBits(bmpData)
bmp.Dispose()
Dim colsCnt As List(Of RgbPixels) = cols.GroupBy(Function(g) New With {Key .R …Run Code Online (Sandbox Code Playgroud)