1

Emgu CV 2.4.2を使用していて、次のアルゴリズムを実行したいと思います。

  1. ブロブを取得する
  2. 計算を高速化するためにROIを設定する
  3. ブロブから極小値のピクセル位置を取得します
  4. ブロブを分割する
  5. 境界の長方形を分割されたブロブに描画します

手順1-2を実行し、BGStatModelを使用してblobを抽出しました。これは私が得た結果です:

ブロブ画像

垂直投影で極小値のピクセル位置を取得したい。それを取得した後、私はブロブを分割し、次のように長方形を描きたいです:

垂直投影画像

ブロブ領域のすべてのピクセルをチェックして極小値のピクセル位置を取得しようとしましたが、アプリケーションの実行が非常に遅くなります。これが私のコードです:

Point minPix = new Point(0,0);

//copy the foreground frame
Image<Gray, Byte> foreFrame_copy = foreFrame.Copy();

//find the contour
Contour<Point> contours = foreFrame.FindContours(
    CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
    RETR_TYPE.CV_RETR_EXTERNAL);

//looping every contour
while (contours != null)
{
    double PPixel = contours.Area;
    if (PPixel >= 1400)
    {
        //get the contour width
        WR = contours.BoundingRectangle.Width;
        //divide the contour using estimated pixel position
        Num = Convert.ToInt32(WR / 40);

    if (Num > 1)
    {
        //save the estimated pixel position for ROI in arraylist
        ArrayList XList = new ArrayList();
        for (int i = 1; i <= Num; i++)
        {
            int x = i * WR / Num;
            XList.Add(x);
        }

        //get the estimated pixel position 
        foreach (int pos in Xlist)
        {
            //roiWidth= 10px
            int roiWidth = (pos-5) + (pos+5);
            //roiHeight= 20px
            int roiHeight = 20;

            int pixValue = 0;
            //STEP 2: set the ROI to speed up computation
            foreFrame_copy.ROI = new Rectangle(contours.BoundingRectangle.X, contours.BoundingRectangle.Y, roiWidth, roiHeight);
            for (int i = (pos-5); i < roiWidth; i++)
            {
                for (int j = (pos-5); j < (pos+5); j++)
                {
                    pixValue = foreFrame_copy.Data[i, j, 0];
                    //find the white pixel
                    if (pixValue == 255) {
                        //find the position of minimum pixel
                        if (j < j-1) {
                        minPix.X = i;
                        minPix.Y = j;
                        }
                    }

                }
            }
        }

    }
    //draw the red rectangle
    estimatedFrame.Draw(contours.BoundingRectangle, new Bgr(Color.Red), 1);
    contours = contours.HNext;
}
else
{
    contours = contours.HNext;
}
}
//show frame in framebox
blobBox.Image = foreFrame_copy;
estimatedBox.Image = estimatedFrame;

Emgu CVを使用してステップ2〜5を最速で実行する方法を教えてください。誰かがこれらの3つのステップといくつかのコードを詳しく説明してくれれば幸いです。

よろしくお願いします、デビッド

4

1 に答える 1

0

わかりましたので、質問は今より明確になります。個人的には、あなたが参考にしている論文は一般性がないためにあまり良くないという点で mmgp ユーザーに同意します。これは、非常に特定のシナリオ用にコーディングされており、制御された環境に関するいくつかの強い仮定があります。

良い出発点として、垂直および水平投影と絶対最大点を計算する方法を提供します

   private void ComputeProjections(Image<Bgr, byte> inputImage)
    {                        
        Image<Gray, Byte> inputGrayImage = inputImage.Convert<Gray, Byte>();
        Matrix<float> imgMatHorizontal = new Matrix<float>(inputGrayImage.Height, 1, 1);
        Matrix<float> imgMatVertical = new Matrix<float>(1, inputGrayImage.Width, 1);

        inputGrayImage.Reduce<float>(imgMatHorizontal, REDUCE_DIMENSION.SINGLE_COL, REDUCE_TYPE.CV_REDUCE_AVG);
        inputGrayImage.Reduce<float>(imgMatVertical, REDUCE_DIMENSION.SINGLE_ROW, REDUCE_TYPE.CV_REDUCE_AVG);
        double minH, maxH, minV, maxV;
        Point minLocH, maxLocH, minLocV, maxLocV;
        imgMatHorizontal.MinMax(out minH, out maxH, out minLocH, out maxLocH);
        imgMatVertical.MinMax(out minV, out maxV, out minLocV, out maxLocV);

        Image<Gray, Byte> maskProvaH = new Image<Gray, byte>(new Size((int)(maxH - minH + 1), imgMatHorizontal.Rows));
        Image<Gray, Byte> maskProvaV = new Image<Gray, byte>(new Size(imgMatVertical.Cols, (int)(maxV - minV + 1)));

        for (int i = 0; i < imgMatHorizontal.Rows; i++)
            maskProvaH.Draw(new CircleF(new PointF((float)(imgMatHorizontal[i, 0] - minH), i), 1f), new Gray(255), 1);

        for (int i = 0; i < imgMatVertical.Cols; i++)
            maskProvaV.Draw(new CircleF(new PointF(i, (float)(imgMatVertical[0, i] - minV)), 1f), new Gray(255), 1);

        inputImage.Draw(new CircleF(new PointF(minLocV.X, minLocH.Y), 2), new Bgr(Color.Green), 1);
        //imageBoxProjected.Image = inputGrayImage;
        imageBoxHorizProj.Image = maskProvaH;
        //imageBoxVerticProj.Image = maskProvaV;

    }

参照されている論文のように極大値を見つけることに興味がある場合は、(水平投影のコード) のような単純な極大値検索の実装を開始できます。

List<Point> localMaxima = new List<Point>();
        imgMatHorizontal.MinMax(out minH, out maxH, out minLocH, out maxLocH);

        Image<Gray, Byte> maskProvaH = new Image<Gray, byte>(new Size((int)(maxH - minH + 1), imgMatHorizontal.Rows));
        for (int i = 0; i < imgMatHorizontal.Rows; i++)
            maskProvaH.Draw(new CircleF(new PointF((float)(imgMatHorizontal[i, 0] - minH), i), 1f), new Gray(255), 1);

        //// Absolute Horizontal Projection Maxima Drawing
        //inputGrayImage.Draw(new Cross2DF(new PointF(maxLocH.X, maxLocH.Y), 2, 2), new Gray(255), 2);

        // Local maximas search
        for (int i = imgMatHorizontal.Rows - 2; i > 1; i--)
        {
            float prev = imgMatHorizontal[i + 1, 0];
            float curr = imgMatHorizontal[i, 0];
            float next = imgMatHorizontal[i - 1, 0];
            if (curr >= prev && curr >= next)
                localMaxima.Add(new Point((int)curr, i));
        }

このコードは、私の YouTube デモの 1 つからのものです。

プロジェクションを使用した顔の特徴のデモ

残りの手順は非常に簡単で、必要に応じて調整したり、ペーパーで提案されているいくつかの交差比率のしきい値に従うことができます。

于 2012-12-12T20:38:12.747 に答える