Hello,
could someone be so kind to give advice or point me in the right direction for
the following circumstance:
I am currently working on a directshow project that is taking input from a USB
web cam and displaying the live video in its normal "default"
colors. what i want to do is filter these colors to just 2 colors. example: i
have a text document being displayed in my application, i would like to make
the text Red and the background Black.
my current method is taking each frame, determine the pixel brightness, if its
over 60% transform that pixel red else black using Unsafe code in c#, i know
there must be a better method,
thank you in advance.
don
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It looks like most of the suggestions I would make for such a project you have
already discovered:
Walk each pixel
Don't look for a hard coded value (ie 255, 255, 255), but use a threshold value.
Use Unsafe mode for decent performance
Without having tried it to see the results, anything I can suggest would be a
vague guess. However, if I were to approach this project, I'd be thinking
along the lines of using 24 bit RGB colors. As I examine a pixel, if I decide
it's going to be black, just paint it black. However, if I were thinking red,
I would just set the G & B values to 0, and set the new R value to (255 -
old R value). This would allow for some shading rather than everything being
completely binary.
But without being able to try it and experiment, it's hard for me to say
whether this will result in clearer output than what you are already doing.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I don't think it is correct to say that there is a "formula" for
finding the threshold.
The problem is that there will be minor variations in how "white"
the paper you are examining is. So, something that just looks white to you or
me, the computer will see as slightly grey. And the bottom right corner of the
page may be slightly different than top left. If you were going to do some
all-up high quality professional grade app, I'd be thinking that you do an
analysis of all the pixels on the page and calculate this for yourself. If
that's your intent, good luck.
Failing that, just pick some numbers for yourself. If 0,0,0 is black
indicating the letters we want to show as red, and 255,255,255 is the white
background you want to turn black, pick some method (maybe just adding the 3
RGB values together) then pick some value (< 200) and give it a try. Change
to suit, and maybe provide a way for the user to fiddle with it if they aren't
getting the results they want.
BTW, if performance is an issue, there are a variety of ways to improve what
you have there. However, they will add complexity, so if you are getting the
perf you want, perhaps you should leave it alone.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It really surprises me that DirectShow or AForge doesn't have this
functionality on a lower level by accessing the video stream directly instead
of my method of creating a bitmap from the stream, running that bitmap through
the color filter algorithms and in most cases running it through interpolation
methods for digital zoom. it just seems my attempt is more brute force than
efficient. thank you for all your responses,, i think i may have to go lower
than directX for video processing with some CCD or CMOS cams with low level
SDK's.
Don
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello,
could someone be so kind to give advice or point me in the right direction for
the following circumstance:
I am currently working on a directshow project that is taking input from a USB
web cam and displaying the live video in its normal "default"
colors. what i want to do is filter these colors to just 2 colors. example: i
have a text document being displayed in my application, i would like to make
the text Red and the background Black.
my current method is taking each frame, determine the pixel brightness, if its
over 60% transform that pixel red else black using Unsafe code in c#, i know
there must be a better method,
thank you in advance.
don
It looks like most of the suggestions I would make for such a project you have
already discovered:
Without having tried it to see the results, anything I can suggest would be a
vague guess. However, if I were to approach this project, I'd be thinking
along the lines of using 24 bit RGB colors. As I examine a pixel, if I decide
it's going to be black, just paint it black. However, if I were thinking red,
I would just set the G & B values to 0, and set the new R value to (255 -
old R value). This would allow for some shading rather than everything being
completely binary.
But without being able to try it and experiment, it's hard for me to say
whether this will result in clearer output than what you are already doing.
what is the formula for finding the threshold, here is the code for inverting
the image, which is very fast:
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
unsafe
{
byte p = ( byte)( void*)Scan0;
int nOffset = stride - b.Width * 3;
int nWidth = b.Width * 3;
for (int y = 0; y < b.Height; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
p = (byte)(255 - p);
++p;
}
p += nOffset;
}
}
b.UnlockBits(bmData);
I don't think it is correct to say that there is a "formula" for
finding the threshold.
The problem is that there will be minor variations in how "white"
the paper you are examining is. So, something that just looks white to you or
me, the computer will see as slightly grey. And the bottom right corner of the
page may be slightly different than top left. If you were going to do some
all-up high quality professional grade app, I'd be thinking that you do an
analysis of all the pixels on the page and calculate this for yourself. If
that's your intent, good luck.
Failing that, just pick some numbers for yourself. If 0,0,0 is black
indicating the letters we want to show as red, and 255,255,255 is the white
background you want to turn black, pick some method (maybe just adding the 3
RGB values together) then pick some value (< 200) and give it a try. Change
to suit, and maybe provide a way for the user to fiddle with it if they aren't
getting the results they want.
BTW, if performance is an issue, there are a variety of ways to improve what
you have there. However, they will add complexity, so if you are getting the
perf you want, perhaps you should leave it alone.
It really surprises me that DirectShow or AForge doesn't have this
functionality on a lower level by accessing the video stream directly instead
of my method of creating a bitmap from the stream, running that bitmap through
the color filter algorithms and in most cases running it through interpolation
methods for digital zoom. it just seems my attempt is more brute force than
efficient. thank you for all your responses,, i think i may have to go lower
than directX for video processing with some CCD or CMOS cams with low level
SDK's.
Don