Trong mã của tôi, tôi lấy khung từ máy ảnh với con trỏ tới đối tượng không được quản lý, thực hiện một số phép tính và sau đó tôi hiển thị nó trên một điều khiển bằng hình ảnh.
Trước khi tôi đi xa hơn trong ứng dụng này với tất cả các chi tiết, tôi muốn chắc chắn rằng mã cơ sở cho quá trình này là tốt. Cụ thể, tôi muốn:
- giữ thời gian thực hiện tối thiểu và tránh các hoạt động không cần thiết, chẳng hạn như sao chép nhiều hình ảnh hơn mức cần thiết. Tôi chỉ muốn giữ lại các hoạt động thiết yếu
- hiểu xem sự chậm trễ trong quá trình tính toán trên mỗi khung có thể có ảnh hưởng bất lợi đến cách hiển thị hình ảnh không (nghĩa là nếu nó không được in như mong đợi) hoặc một số hình ảnh bị bỏ qua
- ngăn chặn các lỗi nghiêm trọng hơn, chẳng hạn như lỗi do bộ nhớ hoặc quản lý luồng hoặc hiển thị hình ảnh.
Vì mục đích này, tôi thiết lập một số dòng mã thử nghiệm (bên dưới), nhưng tôi không thể giải thích kết quả của những gì tôi đã tìm thấy. Nếu bạn có các tệp thực thi của OpenCv, bạn có thể tự mình thử.Thử nghiệm hiển thị bitmap được lấy từ máy ảnh trên Picturebox
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
public partial class FormX : Form
{
private delegate void setImageCallback();
Bitmap _bmp;
Bitmap _bmp_draw;
bool _exit;
double _x;
IntPtr _ImgBuffer;
bool buffercopy;
bool copyBitmap;
bool refresh;
public FormX()
{
InitializeComponent();
_x = 10.1;
// set experimemental parameters
buffercopy = false;
copyBitmap = false;
refresh = true;
}
private void buttonStart_Click(object sender, EventArgs e)
{
Thread camThread = new Thread(new ThreadStart(Cycle));
camThread.Start();
}
private void buttonStop_Click(object sender, EventArgs e)
{
_exit = true;
}
private void Cycle()
{
_ImgBuffer = IntPtr.Zero;
_exit = false;
IntPtr vcap = cvCreateCameraCapture(0);
while (!_exit)
{
IntPtr frame = cvQueryFrame(vcap);
if (buffercopy)
{
UnmanageCopy(frame);
_bmp = SharedBitmap(_ImgBuffer);
}
else
{ _bmp = SharedBitmap(frame); }
// make calculations
int N = 1000000; /*1000000*/
for (int i = 0; i < N; i++)
_x = Math.Sin(0.999999 * _x);
ShowFrame();
}
cvReleaseImage(ref _ImgBuffer);
cvReleaseCapture(ref vcap);
}
private void ShowFrame()
{
if (pbCam.InvokeRequired)
{
this.Invoke(new setImageCallback(ShowFrame));
}
else
{
Pen RectangleDtPen = new Pen(Color.Azure, 3);
if (copyBitmap)
{
if (_bmp_draw != null) _bmp_draw.Dispose();
//_bmp_draw = new Bitmap(_bmp); // deep copy
_bmp_draw = _bmp.Clone(new Rectangle(0, 0, _bmp.Width, _bmp.Height), _bmp.PixelFormat);
}
else
{
_bmp_draw = _bmp; // add reference to the same object
}
Graphics g = Graphics.FromImage(_bmp_draw);
String drawString = _x.ToString();
Font drawFont = new Font("Arial", 56);
SolidBrush drawBrush = new SolidBrush(Color.Red);
PointF drawPoint = new PointF(10.0F, 10.0F);
g.DrawString(drawString, drawFont, drawBrush, drawPoint);
drawPoint = new PointF(10.0F, 300.0F);
g.DrawString(drawString, drawFont, drawBrush, drawPoint);
g.DrawRectangle(RectangleDtPen, 12, 12, 200, 400);
g.Dispose();
pbCam.Image = _bmp_draw;
if (refresh) pbCam.Refresh();
}
}
public void UnmanageCopy(IntPtr f)
{
if (_ImgBuffer == IntPtr.Zero)
_ImgBuffer = cvCloneImage(f);
else
cvCopy(f, _ImgBuffer, IntPtr.Zero);
}
// only works with 3 channel images from camera! (to keep code minimal)
public Bitmap SharedBitmap(IntPtr ipl)
{
// gets unmanaged data from pointer to IplImage:
IntPtr scan0;
int step;
Size size;
OpenCvCall.cvGetRawData(ipl, out scan0, out step, out size);
return new Bitmap(size.Width, size.Height, step, PixelFormat.Format24bppRgb, scan0);
}
// based on older version of OpenCv. Change dll name if different
[DllImport("opencv_highgui246", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr cvCreateCameraCapture(int index);
[DllImport("opencv_highgui246", CallingConvention = CallingConvention.Cdecl)]
public static extern void cvReleaseCapture(ref IntPtr capture);
[DllImport("opencv_highgui246", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr cvQueryFrame(IntPtr capture);
[DllImport("opencv_core246", CallingConvention = CallingConvention.Cdecl)]
public static extern void cvGetRawData(IntPtr arr, out IntPtr data, out int step, out Size roiSize);
[DllImport("opencv_core246", CallingConvention = CallingConvention.Cdecl)]
public static extern void cvCopy(IntPtr src, IntPtr dst, IntPtr mask);
[DllImport("opencv_core246", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr cvCloneImage(IntPtr src);
[DllImport("opencv_core246", CallingConvention = CallingConvention.Cdecl)]
public static extern void cvReleaseImage(ref IntPtr image);
}
quả [lõi kép 2 Duo T6600 2,2 GHz]:
Một. buffercopy = false; copyBitmap = false; refresh = false;
Đây là cấu hình đơn giản hơn. Mỗi khung được lấy lại lần lượt, hoạt động được thực hiện (trong thực tế chúng được dựa trên cùng một khung hình, đây chỉ là tính toán), sau đó kết quả tính toán được in trên đầu hình ảnh và cuối cùng nó được hiển thị trên hình ảnh.
tài liệu OpenCV nói:
OpenCV chức năng 1.x cvRetrieveFrame và cv.RetrieveFrame trở lại hình ảnh lưu trữ bên trong cấu trúc chụp video. Không được phép sửa đổi hoặc giải phóng hình ảnh! Bạn có thể sao chép khung bằng cách sử dụng cvCloneImage() và sau đó thực hiện bất cứ điều gì bạn muốn với bản sao.
Nhưng điều này không ngăn chúng tôi thực hiện thử nghiệm.
Nếu tính toán không mãnh liệt (số lần lặp lại thấp, N), mọi thứ đều ổn và thực tế là chúng ta thao tác bộ đệm ảnh do trình thu thập khung không được quản lý không gây ra vấn đề ở đây.
Lý do là có lẽ họ khuyên nên để nguyên vẹn bộ đệm, trong trường hợp mọi người sẽ sửa đổi cấu trúc của nó (không phải giá trị của nó) hoặc thực hiện các hoạt động không đồng bộ mà không nhận ra nó. Bây giờ chúng tôi lấy khung hình và sửa đổi nội dung của họ lần lượt.
Nếu N tăng (N = 1000000 trở lên), khi số khung hình trên giây không cao, ví dụ với ánh sáng nhân tạo và phơi sáng thấp, mọi thứ có vẻ ok, nhưng sau một thời gian video bị trễ và đồ họa gây ấn tượng trên đó đang nhấp nháy. Với tỷ lệ khung hình cao hơn, nhấp nháy xuất hiện ngay từ đầu, ngay cả khi video vẫn còn là chất lỏng.
Đây có phải là do cơ chế hiển thị hình ảnh trên điều khiển (hoặc làm mới hay bất kỳ thứ gì khác) bằng cách nào đó không đồng bộ và khi hình ảnh đang tìm nạp bộ đệm dữ liệu thì máy ảnh đã sửa đổi trong khi đó, xóa đồ họa?
Hoặc có lý do nào khác không?
Tại sao hình ảnh bị tụt hậu theo cách đó, tức làTôi hy vọng rằng sự chậm trễ do tính toán chỉ có tác dụng bỏ qua các khung nhận được bởi máy ảnh khi tính toán chưa được thực hiện, và thực tế chỉ làm giảm tốc độ khung hình; hoặc cách khác là tất cả các khung hình được nhận và độ trễ do tính toán mang đến cho hệ thống xử lý hình ảnh nhận được phút trước, bởi vì hàng đợi hình ảnh để xử lý tăng theo thời gian.
Thay vào đó, hành vi được quan sát dường như lai giữa hai: có sự chậm trễ vài giây, nhưng điều này dường như không tăng nhiều khi quá trình chụp tiếp tục.
B. buffercopy = true; copyBitmap = false; refresh = false;
Ở đây tôi tạo một bản sao sâu của bộ đệm vào bộ đệm thứ hai, theo lời khuyên của tài liệu OpenCv.
Không có thay đổi nào. Bộ đệm thứ hai không thay đổi địa chỉ của nó trong bộ nhớ trong khi chạy.
C. buffercopy = false; copyBitmap = true; refresh = false;
Bây giờ bản sao (sâu) của bitmap được phân bổ mỗi lần một không gian mới trong bộ nhớ.
Hiệu ứng nhấp nháy đã biến mất, nhưng sự chậm trễ tiếp tục phát sinh sau một thời gian nhất định.
D. buffercopy = false; copyBitmap = false; refresh = true;
Như trước đây.
Vui lòng giúp tôi giải thích các kết quả này!
Thực sự không rõ bạn đang hỏi câu hỏi gì ở đây. Hãy nhớ rằng SO là một diễn đàn Q & A. IIUC, một điều mà bạn dường như đang hỏi là dọc theo dòng "tài liệu nói không làm điều này, nhưng nếu tôi làm điều đó đôi khi nó hoạt động và đôi khi nó không". Vâng - đừng làm thế! –
Không. Có vẻ như bạn vừa đọc một nửa văn bản. Dù sao, nếu bạn đi đến dòng cuối cùng nó sẽ yêu cầu giải thích về kết quả. –
Tôi sợ rằng bạn đang đặt câu hỏi bạn chỉ có thể trả lời vì bạn là người đã thiết kế thử nghiệm. Tôi khuyên bạn nên lên kế hoạch cho một thử nghiệm khác để bạn có thể hiểu kết quả của nó. Việc tái cơ cấu câu hỏi của bạn sẽ rất hay vì khó theo dõi logic hoặc câu hỏi của bạn. –