Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在C语言中加速我的颜色阈值#_C#_Image Processing_Color Space_Threshold - Fatal编程技术网

C# 如何在C语言中加速我的颜色阈值#

C# 如何在C语言中加速我的颜色阈值#,c#,image-processing,color-space,threshold,C#,Image Processing,Color Space,Threshold,我正在研究基于颜色的目标跟踪,我使用EmguCV库将我的彩色图像阈值化为二值黑白图像。阈值本身非常快,在320x240图像上为50毫秒。我使用RG色度空间,所以有一些必要的计算 现在我尝试使用指针来加速它,但结果与我使用emguCV时的结果非常相似(每幅图像大约50毫秒) 我想问,如果有专家能帮助我,我做错了什么。下面是我的颜色阈值实现的简短代码片段。它是基于这个的: 公共静态位图阈值rgchroma(位图原始,双角度最小, 双角度最大值、双最小值、双最大值) { 位图bimg=新位图(原始.W

我正在研究基于颜色的目标跟踪,我使用EmguCV库将我的彩色图像阈值化为二值黑白图像。阈值本身非常快,在320x240图像上为50毫秒。我使用RG色度空间,所以有一些必要的计算

现在我尝试使用指针来加速它,但结果与我使用emguCV时的结果非常相似(每幅图像大约50毫秒)

我想问,如果有专家能帮助我,我做错了什么。下面是我的颜色阈值实现的简短代码片段。它是基于这个的:

公共静态位图阈值rgchroma(位图原始,双角度最小,
双角度最大值、双最小值、双最大值)
{
位图bimg=新位图(原始.Width、原始.Height、PixelFormat.format1bppingdexed);
BitmapData imgData=original.LockBits(新矩形(0,0,original.Width,original.Height),ImageLockMode.ReadOnly,original.PixelFormat);
BitmapData bimgData=bimg.LockBits(新矩形(0,0,bimg.Width,bimg.Height),ImageLockMode.ReadWrite,bimg.PixelFormat);
int pixelSize=3;
双r,g,角,sat;
不安全的
{
字节*R,G,B;
字节*行;
int RGBSum;
对于(int y=original.Height-1;y>=0;y--)
{
行=(字节*)imgData.Scan0+(y*imgData.Stride);
对于(int x=original.Width-1;x>=0;x--)
{
//获取rgb值
B=&行[x*像素大小];
G=&行[x*像素大小+1];
R=&行[x*像素大小+2];
RGBSum=*R+*G+*B;
如果(RGBSum==0)
{
SetIndexedPixel(x,y,bimgData,false);
继续;
}
//计算rg色度颜色空间的r ang g
r=(双)*r/RGBSum;
g=(双)*g/RGBSum;
//以及角度和饱和度
角度=GetAngleRad(r,g)*(180.0/Math.PI);
sat=Math.Sqrt(Math.Pow(g,2)+Math.Pow(r,2));
//设置像素黑色或白色的条件
如果((角度>=angleMin&&angle=satMin&&sat>3);
字节*p=(字节*)bmd.Scan0.ToPointer();
字节掩码=(字节)(0x80>>(x&0x7));
如果(像素)
p[指数]|=遮罩;
其他的
p[索引]&=(字节)(掩码^0xff);
}
专用静态双GetAngleRad(双x,双y)
{
如果(x-_rgChromaOriginX==0)
返回0.0;
双角度=Math.Atan((y-_rgChromaOriginY)/(x-_rgChromaOriginX));//10ms
如果(x<\u rgChromaOriginX&&y>\u rgChromaOriginY)
角度=角度+数学.PI;
否则,如果(x<\u rgChromaOriginX&y<\u rgChromaOriginY)
角度=角度+数学.PI;
否则,如果(x>\r颜色与y<\r颜色与y)
角度=角度+2*Math.PI;
返回角;
}

您正在对每个像素进行大量不必要的计算,计算精确值只是为了检查它们是否在某些限制内。您可以通过预先计算对限制的一些调整来简化比较

最简单的替代方法是饱和,你做的是平方根,你可以通过平方限制来避免

double satMin2 = satMin*satMin;
double satMax2 = satMax*satMax;
// ...
sat2 = g*g + r*r;

//conditions to set pixel black or white
if ((angle >= angleMin && angle <= angleMax) && (sat2 >= satMin2 && sat <= satMax2))
double satMin2=satMin*satMin;
双satMax2=satMax*satMax;
// ...
sat2=g*g+r*r;
//设置像素黑色或白色的条件

如果((angle>=angleMin&&angle=satMin2&&sat为了完整性,这里是RG色度颜色空间中阈值图像的修改版本,它比我问题中的版本快2倍多

公共静态位图阈值RGChroma(位图原始、矩形roi、双角度、, 双宽度、双最小值、双最大值) { 位图bimg=新位图(原始.Width、原始.Height、PixelFormat.format1bppingdexed)

BitmapData imgData=original.LockBits(新矩形(0,0,original.Width,original.Height),ImageLockMode.ReadOnly,original.PixelFormat);
BitmapData bimgData=bimg.LockBits(新矩形(0,0,bimg.Width,bimg.Height),ImageLockMode.ReadWrite,bimg.PixelFormat);
int pixelSize=3;
双r,g,sat,m;
双satMin2=satMin*satMin;
双satMax2=satMax*satMax;
双cr=数学Sin((2*Math.PI*角度)/360.0);
双重心=数学Cos((2*Math.PI*角度)/360.0);
//我使用预先计算的值来代替(Math.Cos(2*width/180.0)+1)/2.0。
双w2=宽度;
不安全的
{
字节*R,G,B;
字节*行;
int RGBSum;
对于(int y=original.Height-1;y>=0;y--)
{
行=(字节*)imgData.Scan0+(y*imgData.Stride);
对于(int x=original.Width-1;x>=0;x--)
{
B=&行[x*像素大小];
G=&行[x*像素大小+1];
R=&行[x*像素大小+2];
RGBSum=*R+*G+*B;
如果(RGBSum==0)
{
SetIndexedPixel(x,y,bimgData,false);
继续;
}
r=(双)*r/RGBSum-rgChromaOriginX;
g=(双)*g/RGBSum-rgChromaOriginY;
m=cr*r+cg*g;
sat=r*r+g*g;

如果(m>0&&m*m>w2*w2*sat&&sat>=satMin2&&sat非常感谢。只需修改饱和度及其范围,就可以在大约20毫秒的时间内,从50到30加速阈值。我还发现RG色度的这一优点,它们展示了如何通过删除Atan来加速阈值。我将发布我的更正版本,其中我的电脑上的h阈值为320x240,仅需18毫秒。
double satMin2 = satMin*satMin;
double satMax2 = satMax*satMax;
// ...
sat2 = g*g + r*r;

//conditions to set pixel black or white
if ((angle >= angleMin && angle <= angleMax) && (sat2 >= satMin2 && sat <= satMax2))
public static Bitmap ThresholdRGChroma(Bitmap original, Rectangle roi, double angle, double width, double satMin, double satMax) { Bitmap bimg = new Bitmap(original.Width, original.Height, PixelFormat.Format1bppIndexed);

        BitmapData imgData = original.LockBits(new Rectangle(0, 0, original.Width, original.Height), ImageLockMode.ReadOnly, original.PixelFormat);
        BitmapData bimgData = bimg.LockBits(new Rectangle(0, 0, bimg.Width, bimg.Height), ImageLockMode.ReadWrite, bimg.PixelFormat);

        int pixelSize = 3;

        double r, g, sat, m;

        double satMin2 = satMin * satMin;
        double satMax2 = satMax * satMax;

        double cr = Math.Sin((2 * Math.PI * angle) / 360.0);
        double cg = Math.Cos((2 * Math.PI * angle) / 360.0);

        // Instead of (Math.Cos(2 * width / 180.0) + 1) / 2.0 I'm using pre-calculated <1; 0> values.
        double w2 = -width;

        unsafe
        {
            byte* R, G, B;
            byte* row;
            int RGBSum;

            for (int y = original.Height - 1; y >= 0; y--)
            {
                row = (byte*)imgData.Scan0 + (y * imgData.Stride);

                for (int x = original.Width - 1; x >= 0; x--)
                {
                    B = &row[x * pixelSize];
                    G = &row[x * pixelSize + 1];
                    R = &row[x * pixelSize + 2];

                    RGBSum = *R + *G + *B;

                    if (RGBSum == 0)
                    {
                        SetIndexedPixel(x, y, bimgData, false);
                        continue;
                    }

                    r = (double)*R / RGBSum - _rgChromaOriginX;
                    g = (double)*G / RGBSum - _rgChromaOriginY;

                    m = cr * r + cg * g;
                    sat = r * r + g * g;

                    if (m > 0 && m * m > w2 * w2 * sat && sat >= satMin2 && sat <= satMax2)
                        SetIndexedPixel(x, y, bimgData, true);
                    else
                        SetIndexedPixel(x, y, bimgData, false);
                }
            }
        }

        bimg.UnlockBits(bimgData);
        original.UnlockBits(imgData);

        return bimg;
    }