문제

색상을 기반으로 객체를 추적하고 있으며 EMGUCV 라이브러리를 사용하여 임계 값 내 흑백 이미지를 이진 흑백 이미지로 사용했습니다.임계 값 자체는 320x240 이미지에서 50ms입니다.RG 색치 색상 공간을 사용하고있어 필연적으로 계산이 있습니다.

이제는 포인터를 사용하여 속도를 높이려고 노력하고 있지만 결과는 내가 EMGUCV (이미지 당 약 50ms)로 한 것과 매우 유사합니다.

나는 나를 도울 수있는 몇 가지 전문가가있는 경우, 내가 무엇을 잘못하고 있는지 묻고 싶습니다.여기 내 색상 임계 값 구현의 짧은 코드 스 니펫이 있습니다.이 하나의 http://www.bobpowell.net/onebit.htm .

public static Bitmap ThresholdRGChroma(Bitmap original, double angleMin,
            double angleMax, 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, angle, sat;

    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--)
            {
                // get rgb values
                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;
                }

                //calculate r ang g for rg chroma color space
                r = (double)*R / RGBSum;
                g = (double)*G / RGBSum;

                //and angle and saturation
                angle = GetAngleRad(r, g) * (180.0 / Math.PI);
                sat = Math.Sqrt(Math.Pow(g, 2) + Math.Pow(r, 2));

                //conditions to set pixel black or white
                if ((angle >= angleMin && angle <= angleMax) && (sat >= satMin && sat <= satMax))
                    SetIndexedPixel(x, y, bimgData, true);
                else
                    SetIndexedPixel(x, y, bimgData, false);
            }

        }
    }

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

    return bimg;
}

private unsafe static void SetIndexedPixel(int x, int y, BitmapData bmd, bool pixel)
{
    int index = y * bmd.Stride + (x >> 3);
    byte* p = (byte*)bmd.Scan0.ToPointer();
    byte mask = (byte)(0x80 >> (x & 0x7));

    if (pixel)
        p[index] |= mask;
    else
        p[index] &= (byte)(mask ^ 0xff);
}

private static double GetAngleRad(double x, double y)
{
    if (x - _rgChromaOriginX == 0)
        return 0.0;
    double angle = Math.Atan((y - _rgChromaOriginY) / (x - _rgChromaOriginX)); // 10ms

    if (x < _rgChromaOriginX && y > _rgChromaOriginY)
        angle = angle + Math.PI;
    else if (x < _rgChromaOriginX && y < _rgChromaOriginY)
        angle = angle + Math.PI;
    else if (x > _rgChromaOriginX && y < _rgChromaOriginY)
        angle = angle + 2 * Math.PI;

    return angle;
}
.
도움이 되었습니까?

해결책

각 픽셀에 대해 불필요한 수학을 많이하고 정확한 값을 계산하여 일부 제한 내에 있는지 확인하는지 확인하십시오.일부 조정을 제한에 미리 저장함으로써 비교를 단순화 할 수 있습니다.

가장 쉬운 대체는 채도를위한 것입니다.대신 한계를 제출하여 피할 수있는 제곱근을하고 있습니다.

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))
.

비슷한 트릭을 각도와 함께 사용할 수 있습니다.Math.atan으로 각도를 계산하는 대신 R 및 G 범위에서 그 한도가 동일한 한계가 무엇인지 알아냅니다.

다른 팁

나는 그것이 더 빠를 것이라면 확실하지 않습니다.그러나 팁을 썼는가?비트 맵을 매우 빠르게 작업하십시오.

완전성을 위해 RG 색치 색 공간에서 임계 값의 수정 된 버전은 내 질문의 버전보다 2 배 빠릅니다.

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; }
.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top