/// <summary>
        /// draw overlay(has transparent background ) on bg
        /// </summary>
        /// <param name="bg"></param>
        /// <param name="overlay"></param>
        public unsafe static void DrawOverlay(Mat bg, Mat overlay)
        {
            if (bg.Size() != overlay.Size())
            {
                throw new System.ArgumentException("bg.Size()!=overlay.Size()");
            }
            if (overlay.Channels() < 4)
            {
                throw new System.ArgumentException("overlay.Channels()<4");
            }
            int colsOverlay = overlay.Cols;
            int rowsOverlay = overlay.Rows;

            //https://stackoverflow.com/questions/54069766/overlaying-an-image-over-another-image-both-with-transparent-background-using-op
            for (int i = 0; i < rowsOverlay; i++)
            {
                Vec3b *pBg      = (Vec3b *)bg.Ptr(i);
                Vec4b *pOverlay = (Vec4b *)overlay.Ptr(i);
                for (int j = 0; j < colsOverlay; j++)
                {
                    Vec3b *pointBg      = pBg + j;
                    Vec4b *pointOverlay = pOverlay + j;
                    if (pointOverlay->Item3 != 0)
                    {
                        pointBg->Item0 = pointOverlay->Item0;
                        pointBg->Item1 = pointOverlay->Item1;
                        pointBg->Item2 = pointOverlay->Item2;
                    }
                }
            }
        }
Example #2
0
    OpenCvSharp.Mat Draw(
        DrawingData data,
        Database database)
    {
        // drawing params of stripe with current faces
        int stripe_width = thumbnail_size * 2 + draw_border * 2;

        int stripe_height =
            (thumbnail_size + draw_border) * max_count_in_stripe - draw_border;

        // image for draw the frame and the stripe
        OpenCvSharp.Mat result = new OpenCvSharp.Mat(
            Math.Max(data.frame.Rows + data.depth.Rows, stripe_height),
            Math.Max(data.frame.Cols, data.depth.Cols) + stripe_width,
            OpenCvSharp.MatType.CV_8UC3,
            OpenCvSharp.Scalar.All(0));

        // copy the frame
        int frame_y_offset = (result.Rows - data.frame.Rows - data.depth.Rows) / 2;
        int depth_y_offset = frame_y_offset + data.frame.Rows;

        data.frame.CopyTo(
            result[
                new OpenCvSharp.Rect(
                    0,
                    frame_y_offset,
                    data.frame.Cols,
                    data.frame.Rows)]);

        for (int i = 0; i < data.depth.Rows; ++i)
        {
            unsafe
            {
                UInt16 *src_ptr = (UInt16 *)data.depth.Ptr(i);
                byte *  dst_ptr = (byte *)result.Ptr(depth_y_offset + i);

                for (int j = 0; j < data.depth.Cols; ++j, ++src_ptr, dst_ptr += 3)
                {
                    UInt16 depth = *src_ptr;
                    byte * bgr   = dst_ptr;

                    bgr[0] = bgr[1] = bgr[2] = 0;

                    if (depth == 0)
                    {
                        continue;
                    }

                    if (depth < 256)
                    {
                        bgr[2] = (byte)(256 - depth);
                    }

                    if (depth < 256 * 2)
                    {
                        bgr[1] = (byte)(depth / 2);
                    }
                    else
                    {
                        bgr[1] = (byte)(255);
                    }

                    if (depth < 256 * 4)
                    {
                        bgr[0] = (byte)(depth / 4);
                    }
                    else
                    {
                        bgr[0] = (byte)(255);
                    }
                }
            }
        }

        // clone faces data for random access
        List <Tuple <int, FaceData> > faces = new List <Tuple <int, FaceData> >();

        foreach (KeyValuePair <int, FaceData> pair in data.faces)
        {
            faces.Add(new Tuple <int, FaceData>(pair.Key, pair.Value));
        }



        // make order with recognized first
        // pair<match_database_index, index in faces>
        List <Tuple <int, int> > order = new List <Tuple <int, int> >();

        for (int i = 0; i < faces.Count; ++i)
        {
            order.Add(new Tuple <int, int>(faces[i].Item2.match_database_index, i));
        }

        order.Sort();

        // draw alive faces
        for (int order_i = 0; order_i < order.Count; ++order_i)
        {
            FaceData face = faces[order[order_i].Item2].Item2;

            // draw circles of faces appeared on this frame
            if (face.frame_id == data.frame_id && !face.lost)
            {
                // get points
                List <Point> points = face.sample.getLandmarks();

                // compute center
                OpenCvSharp.Point2f center = new OpenCvSharp.Point2f(0, 0);

                for (int j = 0; j < points.Count; ++j)
                {
                    center.X += points[j].x;
                    center.Y += points[j].y;
                }
                center *= 1.0 / points.Count;


                // compute radius
                double radius = 0;

                for (int j = 0; j < points.Count; ++j)
                {
                    radius += OpenCvSharp.Point2f.Distance(new OpenCvSharp.Point2f(points[j].x, points[j].y), center);
                }

                radius *= 1.5 / points.Count;

                radius *= 2;

                // choose color
                OpenCvSharp.Scalar color =
                    face.match_database_index < 0 ?
                    new OpenCvSharp.Scalar(0, 0, 255) :                              // red color for unrecognized
                    new OpenCvSharp.Scalar(0, 255, 0);                               // green color for recognizerd

                for (int k = 0; k < (data.depth.Empty() ? 1 : 2); ++k)
                {
                    int y_offset = (k == 0 ? frame_y_offset : depth_y_offset);

                    // dashed circle for weak face samples
                    if (face.weak)
                    {
                        // draw dashed cirle for weak samples
                        int n = 8;
                        for (int i = 0; i < n; ++i)
                        {
                            OpenCvSharp.Cv2.Ellipse(
                                result,
                                (OpenCvSharp.Point)(center + new OpenCvSharp.Point2f(0f, y_offset)),
                                new OpenCvSharp.Size(radius, radius),
                                (face.frame_id * 2) % 360,
                                (i * 2 + 0) * 180 / n,
                                (i * 2 + 1) * 180 / n,
                                color,
                                3,
                                OpenCvSharp.LineTypes.AntiAlias);
                        }
                    }
                    else
                    {
                        OpenCvSharp.Cv2.Circle(
                            result,
                            (OpenCvSharp.Point)(center + new OpenCvSharp.Point2f(0f, y_offset)),
                            (int)radius,
                            color,
                            3,
                            OpenCvSharp.LineTypes.AntiAlias);
                    }
                }
            }

            // no - draw the stripe
            if (order_i < max_count_in_stripe)
            {
                // place for thumbnail from the frame
                OpenCvSharp.Rect sample_rect = new OpenCvSharp.Rect(
                    data.frame.Cols + draw_border,
                    (thumbnail_size + draw_border) * order_i,
                    thumbnail_size,
                    thumbnail_size);

                // place for thumbnail from the database
                OpenCvSharp.Rect match_rect = new OpenCvSharp.Rect(
                    data.frame.Cols + draw_border * 2 + thumbnail_size,
                    (thumbnail_size + draw_border) * order_i,
                    thumbnail_size,
                    thumbnail_size);

                // make thumbnail from the frame
                Database.makeThumbnail(face.sample).CopyTo(result[sample_rect]);

                // fade if image is lost
                if (face.draw_multilier < 1)
                {
                    result[sample_rect] *= face.draw_multilier;
                }

                if (face.match_database_index < 0)
                {
                    // gray color for unrecognized persons
                    result[match_rect].SetTo(128 * face.draw_multilier);
                }
                else
                {
                    // thumbnail from the database for recognized persons
                    database.thumbnails[face.match_database_index].CopyTo(result[match_rect]);

                    // fade if image is lost
                    if (face.draw_multilier < 1)
                    {
                        result[match_rect] *= face.draw_multilier;
                    }
                }
            }
        }

        return(result);
    }
Example #3
0
    OpenCvSharp.Mat Draw(
        DrawingData data,
        Database database)
    {
        // drawing params of stripe with current faces
        int stripe_width = thumbnail_size * 2 + draw_border * 2;

        int stripe_height =
            (thumbnail_size + draw_border) * max_count_in_stripe - draw_border;

        // image for draw the frame and the stripe
        OpenCvSharp.Mat result = new OpenCvSharp.Mat(
            Math.Max(data.frame.Rows + data.depth.Rows, stripe_height),
            Math.Max(data.frame.Cols, data.depth.Cols) + stripe_width,
            OpenCvSharp.MatType.CV_8UC3,
            OpenCvSharp.Scalar.All(0));

        // copy the frame
        int frame_y_offset = (result.Rows - data.frame.Rows - data.depth.Rows) / 2;
        int depth_y_offset = frame_y_offset + data.frame.Rows;

        data.frame.CopyTo(
            result[
                new OpenCvSharp.Rect(
                    0,
                    frame_y_offset,
                    data.frame.Cols,
                    data.frame.Rows)]);

        for (int i = 0; i < data.depth.Rows; ++i)
        {
            unsafe
            {
                UInt16 *src_ptr = (UInt16 *)data.depth.Ptr(i);
                byte *  dst_ptr = (byte *)result.Ptr(depth_y_offset + i);

                for (int j = 0; j < data.depth.Cols; ++j, ++src_ptr, dst_ptr += 3)
                {
                    UInt16 depth = *src_ptr;
                    byte * bgr   = dst_ptr;

                    bgr[0] = bgr[1] = bgr[2] = 0;

                    if (depth == 0)
                    {
                        continue;
                    }

                    if (depth < 256)
                    {
                        bgr[2] = (byte)(256 - depth);
                    }

                    if (depth < 256 * 2)
                    {
                        bgr[1] = (byte)(depth / 2);
                    }
                    else
                    {
                        bgr[1] = (byte)(255);
                    }

                    if (depth < 256 * 4)
                    {
                        bgr[0] = (byte)(depth / 4);
                    }
                    else
                    {
                        bgr[0] = (byte)(255);
                    }
                }
            }
        }

        // clone faces data for random access
        List <Tuple <int, FaceData> > faces = new List <Tuple <int, FaceData> >();

        foreach (KeyValuePair <int, FaceData> pair in data.faces)
        {
            faces.Add(new Tuple <int, FaceData>(pair.Key, pair.Value));
        }



        // make order with recognized first
        // pair<match_database_index, index in faces>
        List <Tuple <int, int> > order = new List <Tuple <int, int> >();

        for (int i = 0; i < faces.Count; ++i)
        {
            order.Add(new Tuple <int, int>(faces[i].Item2.match_database_index, i));
        }

        order.Sort();

        // draw alive faces
        for (int order_i = 0; order_i < order.Count; ++order_i)
        {
            FaceData face = faces[order[order_i].Item2].Item2;

            // draw circles of faces appeared on this frame
            if (face.frame_id == data.frame_id && !face.lost)
            {
                // get points
                List <Point> points      = face.sample.getLandmarks();
                List <Point> iris_points = face.sample.getIrisLandmarks();

                // compute center
                OpenCvSharp.Point2f center = new OpenCvSharp.Point2f(0, 0);

                for (int j = 0; j < points.Count; ++j)
                {
                    center.X += points[j].x;
                    center.Y += points[j].y;
                }
                center *= 1.0 / points.Count;


                // compute radius
                double radius = 0;

                for (int j = 0; j < points.Count; ++j)
                {
                    radius += OpenCvSharp.Point2f.Distance(new OpenCvSharp.Point2f(points[j].x, points[j].y), center);
                }

                radius *= 1.5 / points.Count;

                radius *= 2;

                RawSample.Rectangle rectangle = face.sample.getRectangle();

                // set a point to place information for this face
                OpenCvSharp.Point2f text_point = new OpenCvSharp.Point2f(
                    rectangle.x + rectangle.width + 3,
                    rectangle.y + 10);
                const float text_line_height = 22;

                // choose color
                OpenCvSharp.Scalar color =
                    face.match_database_index < 0 ?
                    new OpenCvSharp.Scalar(0, 0, 255) :                              // red color for unrecognized
                    new OpenCvSharp.Scalar(0, 255, 0);                               // green color for recognizerd

                for (int k = 0; k < (data.depth.Empty() ? 1 : 2); ++k)
                {
                    int y_offset = (k == 0 ? frame_y_offset : depth_y_offset);

                    // dashed circle for weak face samples
                    if (face.weak)
                    {
                        // draw dashed cirle for weak samples
                        int n = 8;
                        for (int i = 0; i < n; ++i)
                        {
                            OpenCvSharp.Cv2.Ellipse(
                                result,
                                (OpenCvSharp.Point)(center + new OpenCvSharp.Point2f(0f, y_offset)),
                                new OpenCvSharp.Size(radius, radius),
                                (face.frame_id * 2) % 360,
                                (i * 2 + 0) * 180 / n,
                                (i * 2 + 1) * 180 / n,
                                color,
                                3,
                                OpenCvSharp.LineTypes.AntiAlias);
                        }
                    }
                    else
                    {
                        OpenCvSharp.Cv2.Circle(
                            result,
                            (OpenCvSharp.Point)(center + new OpenCvSharp.Point2f(0f, y_offset)),
                            (int)radius,
                            color,
                            3,
                            OpenCvSharp.LineTypes.AntiAlias);
                    }
                }
                if (face.age_gender_set)
                {
                    // draw
                    AgeGenderEstimator.AgeGender age_gender = face.age_gender;

                    string age_text = "age: ";

                    switch (age_gender.age)
                    {
                    case AgeGenderEstimator.Age.AGE_KID: age_text += "kid    "; break;

                    case AgeGenderEstimator.Age.AGE_YOUNG: age_text += "young  "; break;

                    case AgeGenderEstimator.Age.AGE_ADULT: age_text += "adult  "; break;

                    case AgeGenderEstimator.Age.AGE_SENIOR: age_text += "senior "; break;
                    }

                    age_text += string.Format("years: {0:G3}", age_gender.age_years);

                    puttext(
                        result,
                        age_text,
                        text_point);

                    text_point.Y += text_line_height;

                    puttext(
                        result,
                        age_gender.gender == AgeGenderEstimator.Gender.GENDER_FEMALE ? "gender: female" :
                        age_gender.gender == AgeGenderEstimator.Gender.GENDER_MALE ? "gender: male" : "?",
                        text_point);
                    text_point.Y += text_line_height;

                    text_point.Y += text_line_height / 3;

                    // Console.WriteLine(face.age_gender.age_years);
                }
                if (face.emotion_set)
                {
                    // draw
                    List <EmotionsEstimator.EmotionConfidence> emotions = face.emotion_confidence;

                    for (int j = 0; j < emotions.Count; ++j)
                    {
                        EmotionsEstimator.Emotion emotion = emotions[j].emotion;
                        float confidence = emotions[j].confidence;

                        OpenCvSharp.Cv2.Rectangle(
                            result,
                            new OpenCvSharp.Rect(
                                (int)text_point.X,
                                (int)text_point.Y - (int)text_line_height / 2,
                                (int)(100 * confidence),
                                (int)text_line_height),
                            emotion == EmotionsEstimator.Emotion.EMOTION_NEUTRAL ? new OpenCvSharp.Scalar(255, 0, 0) :
                            emotion == EmotionsEstimator.Emotion.EMOTION_HAPPY ? new OpenCvSharp.Scalar(0, 255, 0) :
                            emotion == EmotionsEstimator.Emotion.EMOTION_ANGRY ? new OpenCvSharp.Scalar(0, 0, 255) :
                            emotion == EmotionsEstimator.Emotion.EMOTION_SURPRISE ? new OpenCvSharp.Scalar(0, 255, 255) :
                            new OpenCvSharp.Scalar(0, 0, 0), -1);

                        puttext(
                            result,
                            emotion == EmotionsEstimator.Emotion.EMOTION_NEUTRAL ? "neutral" :
                            emotion == EmotionsEstimator.Emotion.EMOTION_HAPPY ? "happy" :
                            emotion == EmotionsEstimator.Emotion.EMOTION_ANGRY ? "angry" :
                            emotion == EmotionsEstimator.Emotion.EMOTION_SURPRISE ? "surprise" : "?",
                            text_point + new OpenCvSharp.Point2f(100, 0));

                        text_point.Y += text_line_height;

                        text_point.Y += text_line_height / 3;
                    }
                }
                if (face.active_liveness_status.verdict != ActiveLiveness.Liveness.NOT_COMPUTED)
                {
                    string active_liveness = "";

                    if (face.active_liveness_status.verdict == ActiveLiveness.Liveness.WAITING_FACE_ALIGN)
                    {
                        active_liveness += face.active_liveness_status.verdict.ToString();
                    }
                    else
                    {
                        active_liveness += face.active_liveness_status.check_type.ToString();
                        active_liveness += ": ";
                        active_liveness += face.active_liveness_status.verdict.ToString();
                        active_liveness += " " + face.active_liveness_status.progress_level.ToString();
                    }
                    puttext(result, active_liveness, text_point);

                    text_point.Y += text_line_height;

                    text_point.Y += text_line_height / 3;
                }

//				// draw iris points
//				for(int j = 0; j < iris_points.Count; ++j)
//				{
//					int ms = 1;
//					OpenCvSharp.Scalar icolor = new OpenCvSharp.Scalar(50, 255, 50);
//					int oi = j - 20 * Convert.ToInt32(j >= 20);
//					Point pt1 = iris_points[j];
//					Point pt2 = iris_points[(oi < 19 ? j : j - 15) + 1];
//					OpenCvSharp.Point2f cv_pt1 = new OpenCvSharp.Point2f(pt1.x, frame_y_offset + pt1.y);
//					OpenCvSharp.Point2f cv_pt2 = new OpenCvSharp.Point2f(pt2.x, frame_y_offset + pt2.y);
//
//					if(oi < 5)
//					{
//						icolor = new OpenCvSharp.Scalar(0, 165, 255);
//						if(oi == 0)
//						{
//							double iradius = Math.Sqrt(Math.Pow(pt1.x - pt2.x, 2) + Math.Pow(pt1.y - pt2.y, 2));
//							OpenCvSharp.Cv2.Circle(
//								result,
//								cv_pt1,
//								(int) iradius,
//								icolor,
//								ms,
//								OpenCvSharp.LineTypes.AntiAlias);
//						}
//					}else
//					{
//						OpenCvSharp.Cv2.Line(
//							result,
//							cv_pt1,
//							cv_pt2,
//							icolor,
//							ms,
//							OpenCvSharp.LineTypes.AntiAlias);
//					}
//
//					OpenCvSharp.Cv2.Circle(
//						result,
//						cv_pt1,
//						ms,
//						color,
//						-1,
//						OpenCvSharp.LineTypes.AntiAlias);
//				}
            }

            // no - draw the stripe
            if (order_i < max_count_in_stripe)
            {
                // place for thumbnail from the frame
                OpenCvSharp.Rect sample_rect = new OpenCvSharp.Rect(
                    data.frame.Cols + draw_border,
                    (thumbnail_size + draw_border) * order_i,
                    thumbnail_size,
                    thumbnail_size);

                // place for thumbnail from the database
                OpenCvSharp.Rect match_rect = new OpenCvSharp.Rect(
                    data.frame.Cols + draw_border * 2 + thumbnail_size,
                    (thumbnail_size + draw_border) * order_i,
                    thumbnail_size,
                    thumbnail_size);

                // make thumbnail from the frame
                Database.makeThumbnail(face.sample).CopyTo(result[sample_rect]);

                // fade if image is lost
                if (face.draw_multilier < 1)
                {
                    result[sample_rect] *= face.draw_multilier;
                }

                if (face.match_database_index < 0)
                {
                    // gray color for unrecognized persons
                    result[match_rect].SetTo(128 * face.draw_multilier);
                }
                else
                {
                    // thumbnail from the database for recognized persons
                    database.thumbnails[face.match_database_index].CopyTo(result[match_rect]);

                    // fade if image is lost
                    if (face.draw_multilier < 1)
                    {
                        result[match_rect] *= face.draw_multilier;
                    }
                }
            }
        }

        return(result);
    }