在c#中转换图像

Hug*_*e28 6 c# image type-conversion emgucv

编辑:已解决!有关详细信息,请参阅下面的答案.我无法找到原始问题的答案,但我找到了另一种解决方案

这个问题可能会在其他地方被问到,但我一直在寻找几天,找不到任何有用的东西.

问题:我需要一次性将"Stream"转换为"image(bgr,byte)",是否有一种方法/命令可以直接从System.Drawing.Image.FromStream转换为Emgu.CV.Image(Bgr,Byte)在不脱离转换图像位图,以图像(BGR,字节)

信息:我在Visual Studio 2010中使用c#进行编码,这是我的论文项目的一部分.我正在从网络上的IP摄像机拍摄图像流,并应用许多算法来检测面部/提取面部特征并识别个人面部.在我的笔记本电脑本地相机上我可以实现约25~(给或拿)的FPS,包括算法,因为我不需要转换图像.对于IP摄像机流,我需要多次转换才能达到所需的格式,结果大约为5-8fps.

(我知道我目前的方法是非常低效的,这就是为什么我在这里,我实际上是将图像总共转换5次(甚至是灰度缩放),实际上只使用了我处理器内存的一半(i7,8gb RAM)).它必须是图像(bgr,byte),因为这是算法将使用的唯一格式.

我用来获取图像的代码:

//headers
using System.IO
using System.Threading;
using System.Net;
//request a connection
req = (HttpWebRequest)HttpWebRequest.Create(cameraUrl);
//gives chance for timeout for errors to occur or loss of connection
req.AllowWriteStreamBuffering = true;
req.Timeout = 20000;
//retrieve response (if successfull)
res = req.GetResponse();
//image returned
stream = res.GetResponseStream();
Run Code Online (Sandbox Code Playgroud)

我在后台管理连接,数据,安全等方面有很多东西,我已经缩短到上面的代码.我目前的代码将图像转换为所需的输出:

//Convert stream to image then to bitmap
Bitmap bmpImage = new Bitmap(System.Drawing.Image.FromStream(stream));                    
//Convert to emgu image (desired goal)
currentFrame = new Emgu.CV.Image<Bgr, Byte>(bmpImage);
//gray scale for other uses
gray = currentFrame.Convert<Gray, Byte>();
Run Code Online (Sandbox Code Playgroud)

我知道有一种方法可以暂时在本地保存图像,但出于安全考虑,我需要避免这种情况.我正在寻找更多直接转换以帮助节省处理能力.我忽略了什么吗?所有帮助表示赞赏.

谢谢阅读.(如果有人要求更多细节,我会更新)-Dave

Hug*_*e28 3

我相信我找到了问题的答案。我尝试过使用Vano Maisuradze的内存处理思想,这使得 fps 略有提高(未经测试不会立即明显)。另外,感谢Plinths 的回答,我对多线程有了了解,并且可以随着我的进步而优化它,因为我可以将算法拆分为并行工作。

我想我的原因就是网速!不是实际的算法延迟。正如瓦诺(Vano)用秒表找到速度所指出的那样,算法实际上并没有消耗那么多。因此,如果我使用线程进行优化,无论有没有算法,速度都大致相同,因此在前一帧完成处理时会收集下一帧。

我在一些物理思科路由器上做了一些测试,如果时钟速度和带宽稍微慢一点,就会得到相同的结果,这一点很明显。所以我需要找到一种更快地通过网络检索帧的方法,非常感谢所有回答的人,他们帮助我更好地理解!

结论:

  • 多线程优化
  • 在内存中处理而不是不断转换
  • 更好的网络解决方案(更高的带宽和速度)

编辑:为任何发现此问题寻求帮助的人检索图像并在内存中进行处理的代码

public void getFrames(object sender, EventArgs e)
{//Gets a frame from the IP cam
    //Replace "IPADDRESS", "USERNAME", "PASSWORD" 
    //with respective data for your camera
    string sourceURL = "http://IPADDRESS/snapshot.cgi?user=USERNAME&pwd=PASSWORD";
    //used to store the image retrieved in memory
    byte[] buffer = new byte[640 * 480];
    int read, total = 0;

    //Send a request to the peripheral via HTTP
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(sourceURL);
    WebResponse resp = req.GetResponse();

    //Get the image capture after recieving a request
    //Note: just a screenshot not a steady stream
    Stream stream = resp.GetResponseStream();
    while ((read = stream.Read(buffer, total, 1000)) != 0)
    {
        total += read;
    }//While End

    //Convert memory (byte) to bitmap and store in a picturebox    
    pictureBox1.Image = (Bitmap)Bitmap.FromStream(new MemoryStream(buffer, 0, total));
}//getFrames End

private void button1_Click(object sender, EventArgs e)
{//Trigger an event to start running the function when possible
    Application.Idle += new EventHandler(getFrames);
}//Button1_Click End
Run Code Online (Sandbox Code Playgroud)