Click here to Skip to main content
15,891,607 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
C#
private void cmb_cameras_SelectedIndexChanged(object sender, EventArgs e)
{
    //selected video source
    FinalVideoSource = new VideoCaptureDevice(VideoCaptureDevices[cmb_cameras.SelectedIndex].MonikerString);
    FinalVideoSource.NewFrame += new NewFrameEventHandler(FinalVideoSource_NewFrame);
    FinalVideoSource.Start();
}

void FinalVideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
    try
    {
        using (ImageAttributes attributes = new ImageAttributes())
        {
            LiveImage = (Bitmap)eventArgs.Frame.Clone();
            //create a blank bitmap the same size as original
            //get a graphics object from the new image
            Graphics g = Graphics.FromImage(NewBitmap);
            //create the grayscale ColorMatrix
            ColorMatrix colorMatrix = new ColorMatrix(
            new float[][]
            {
                new float[] {.3f, .3f, .3f, 0, 0},
                new float[] {.59f, .59f, .59f, 0, 0},
                new float[] {.11f, .11f, .11f, 0, 0},
                new float[] {0, 0, 0, 1, 0},
                new float[] {0, 0, 0, 0, 1}
            });
            //create some image attributes
            //ImageAttributes attributes = new ImageAttributes();
            //set the color matrix attribute
            attributes.SetColorMatrix(colorMatrix);
            //draw the original image on the new image
            //using the grayscale color matrix
            g.DrawImage(
                LiveImage,
                new Rectangle(0, 0, LiveImage.Width, LiveImage.Height),
                0, 0,
                LiveImage.Width, LiveImage.Height,
                GraphicsUnit.Pixel, attributes);
                //PB_LiveImage.Image = NewBitmap;
                //g.Dispose();
                //attributes.Dispose();
                //LiveImage.Dispose();
        }
        foreach (int a in IEnum_a)
        {
            foreach (int c in IEnum_c)
            {
                now_color = NewBitmap.GetPixel(c, a);
                if (now_color.ToArgb() == Color.WhiteSmoke.ToArgb())
                    ProcessedBitmap.SetPixel(c, a, Color.Orange);
                else if (now_color.ToArgb() == Color.White.ToArgb())
                    ProcessedBitmap.SetPixel(c, a, Color.Cyan);
                else if (now_color.ToArgb() == Color.DarkGray.ToArgb())
                    ProcessedBitmap.SetPixel(c, a, Color.Red);
                else
                    ProcessedBitmap.SetPixel(c, a, Color.Blue);
            }
        }

        PB_LiveImage.Image = ProcessedBitmap;
    }
    catch (Exception ex)
    {
        MessageBox.Show("Message:\n Kindly closed the application.");
    }

    // Dock the PictureBox to the form and set its background to white.
    // Connect the Paint event of the PictureBox to the event handler method.
    //PB_LiveImage.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint);

}


I got an error from above code that "object is currently in use elsewhere". Which object is used in elsewhere and How do I check it?
Posted
Comments
Garth J Lancaster 27-Feb-13 4:56am    
dude - it might be a bit more helpful if you localise which code line throws the error - try single stepping into and through each procedure - if you have to, set a breakpoint (F9 iirc) on the first code line of each of those procs, hit F5 and wait 'til you get to the breakpoint
rajesh@1989 27-Feb-13 6:31am    
thanks sir!
But it is difficult to find out through breakpoint. Actually exception occurred after few minutes.

1 solution

Its actually pretty easy to figure out what is going on here...

You have a webcam that is sending new frame events to this function. The function does a LOT of image manipulation, then interacts with the UI.

I assume that your webcam is probably sending images between 10-30 frames per second. Trying to run your code above at the webcam frame rate is probably going to result in overlaps on events and trying to access the UI from multiple threads, eventually running into a conflict.

There are a couple ways you can fix this. You can set a flag while processing the image and drop the frames that come in while you are processing the current frame. You could also try to buffer, although I think that would just prolong the problem at hand.

What you should do is a combination of the above and a better way of doing image manipulation. Using GetPixel/SetPixel is probably the worst way to modify pixels on a bitmap. You need to look into using LockBits and pointer's in unsafe code if you want to do it quickly. You can get a speed increase of 10-20 times. I can't tell because the code dump is incomplete, but it looks like you are looping through all the pixels in the image and running a check to change the color, this is very, very slow.

Take a look at how to do LockBits and fast bitmap manipulation, then drop frames while processing and I'm pretty sure your problem will go away.
 
Share this answer
 
Comments
rajesh@1989 5-Mar-13 2:52am    
First of all thank you for your valuable response. But there is same error occured "object is currently in use elsewhere" and it is too slow when I am processing 640X480 image.

void FinalVideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
try
{
System.Console.WriteLine("1: Flag status: "+ flag.ToString());
if (!flag)
{
flag = true;
System.Console.WriteLine("2: Flag status: "+ flag.ToString());
using (ImageAttributes attributes = new ImageAttributes())
{
LiveImage = (Bitmap)eventArgs.Frame.Clone();
//NewBitmap.Size = new Size(LiveImage.Width, LiveImage.Height);
//create a blank bitmap the same size as original
//get a graphics object from the new image
Graphics g = Graphics.FromImage(NewBitmap);
//create the grayscale ColorMatrix
ColorMatrix colorMatrix = new ColorMatrix(
new float[][]
{
new float[] {.3f, .3f, .3f, 0, 0},
new float[] {.59f, .59f, .59f, 0, 0},
new float[] {.11f, .11f, .11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});
attributes.SetColorMatrix(colorMatrix);
//draw the original image on the new image
//using the grayscale color matrix
g.DrawImage(LiveImage, new Rectangle(0, 0, 640, 480),
0, 0, 640, 480, GraphicsUnit.Pixel, attributes);
//ProcessedBitmap = new Bitmap(NewBitmap);
}
#region [Image processing using loop commented]
////foreach (int a in IEnum_a)
////{
//// foreach (int c in IEnum_c)
//// {
//for (int a = 0; a < 480; a++)
//{
// for (int c = 0; c < 640; c++)
// {
// now_color = Duplicate_GrayscaleImg.GetPixel(c, a);
// if (now_color.ToArgb() == Color.WhiteSmoke.ToArgb())
// ProcessedBitmap.SetPixel(c, a, Color.Orange);
// else if (now_color.ToArgb() == Color.White.ToArgb())
// ProcessedBitmap.SetPixel(c, a, Color.Red);
// else if (now_color.ToArgb() == Color.DarkGray.ToArgb())
// ProcessedBitmap.SetPixel(c, a, Color.Red);
// else
// ProcessedBitmap.SetPixel(c, a, Color.Blue);
// }
//}
#endregion
//System.Diagnostics.Stopwatch sWatch = new System.Diagnostics.Stopwatch();
//sWatch.Start();
#region [Image processing using bitlock]

const byte BYTE_255 = 255;
Bitmap24 bm24 = new Bitmap24(NewBitmap);
// Lock the bitmap.
bm24.LockBitmap();

// Invert the pixels.
for (int i = 0; i < NewBitmap.Height * bm24.RowSizeBytes; i++)
{
// bm24.ImageBytes[i] = Convert.ToByte(BYTE_255 - bm24.ImageBytes[i]);
bm24.ImageBytes[i] = (byte)(BYTE_255 - bm24.ImageBytes[i]);
//System.Console.WriteLine(bm24.ImageBytes[i].GetHashCode())

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900