OpenCVSharp 4.5 PCA 主成分分析

用 OpenCVSharp 4.5 跑一遍 OpenCV 官方教程

原 OpenCV 官方教程链接:Introduction to Principal Component Analysis (PCA)

核心函数:PCA

using System;
using OpenCvSharp;

namespace ConsoleApp1
{
    class tutorial42 : ITutorial
    {
        public void Run()
        {
            Mat src = Cv2.ImRead(@"I:\csharp\images\pca_test1.jpg");
            // Check if image is loaded successfully
            if (src.Empty())
            {
                Console.WriteLine("Problem loading image!!!");
                return;
            }
            Cv2.ImShow("src", src);
            // Convert image to grayscale
            Mat gray = new Mat();
            Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
            // Convert image to binary
            Mat bw = new Mat();
            Cv2.Threshold(gray, bw, 50, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
            // Find all the contours in the thresholded image
            Point[][] contours;
            HierarchyIndex[] hierarchy;
            Cv2.FindContours(bw, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone);
            for (int i = 0; i < contours.Length; i++)
            {
                // Calculate the area of each contour
                double area = Cv2.ContourArea(contours[i]);
                // Ignore contours that are too small or too large
                if (area < 1e2 || 1e5 < area) continue;
                // Draw each contour only for visualisation purposes
                Cv2.DrawContours(src, contours, i, new Scalar(0, 0, 255), 2);
                // Find the orientation of each shape
                getOrientation(contours[i], src);
            }
            Cv2.ImShow("output", src);
            Cv2.WaitKey();
            return;

        }

        private void drawAxis(Mat img, Point p, Point q, Scalar colour, double scale = 0.2)
        {
            double angle = Math.Atan2((double)p.Y - q.Y, (double)p.X - q.X); // angle in radians

            double hypotenuse = Math.Sqrt((double)(p.Y - q.Y) * (p.Y - q.Y) + (p.X - q.X) * (p.X - q.X));
            // Here we lengthen the arrow by a factor of scale
            q.X = (int)(p.X - scale * hypotenuse * Math.Cos(angle));
            q.Y = (int)(p.Y - scale * hypotenuse * Math.Sin(angle));
            Cv2.Line(img, p, q, colour, 1, LineTypes.AntiAlias);
            // create the arrow hooks
            p.X = (int)(q.X + 9 * Math.Cos(angle + Cv2.PI / 4));
            p.Y = (int)(q.Y + 9 * Math.Sin(angle + Cv2.PI / 4));

            Cv2.Line(img, p, q, colour, 1, LineTypes.AntiAlias);
            p.X = (int)(q.X + 9 * Math.Cos(angle - Cv2.PI / 4));
            p.Y = (int)(q.Y + 9 * Math.Sin(angle - Cv2.PI / 4));
            Cv2.Line(img, p, q, colour, 1, LineTypes.AntiAlias);
        }
        private double getOrientation(Point[] pts, Mat img)
        {
            //Construct a buffer used by the pca analysis
            int sz = (int)pts.Length;
            Mat data_pts = new Mat(sz, 2, MatType.CV_64F);

            for (int i = 0; i < data_pts.Rows; i++)
            {
                data_pts.At<double>(i, 0) = pts[i].X;
                data_pts.At<double>(i, 1) = pts[i].Y;
            }
            //Perform PCA analysis
            PCA pca_analysis = new PCA(data_pts, new Mat(), PCA.Flags.DataAsRow);
            //Store the center of the object
            Point cntr = new Point((int)(pca_analysis.Mean.At<double>(0, 0)),
                              (int)(pca_analysis.Mean.At<double>(0, 1)));

            //Store the eigenvalues and eigenvectors
            Point2d[] eigen_vecs = new Point2d[2];
            double[] eigen_val = new double[2];
            for (int i = 0; i < 2; i++)
            {
                eigen_vecs[i] = new Point2d(pca_analysis.Eigenvectors.At<double>(i, 0),
                                        pca_analysis.Eigenvectors.At<double>(i, 1));
                eigen_val[i] = pca_analysis.Eigenvalues.At<double>(i);
            }
            // Draw the principal components
            Cv2.Circle(img, cntr, 3, new Scalar(255, 0, 255), 2);
            Point px = new Point((int)(0.02 * eigen_vecs[0].X * eigen_val[0]), (int)(0.02 * eigen_vecs[0].Y * eigen_val[0]));
            Point py = new Point((int)(0.02 * eigen_vecs[1].X * eigen_val[1]), (int)(0.02 * eigen_vecs[1].Y * eigen_val[1]));
            Point p1 = cntr + px;
            Point p2 = cntr - py;

            drawAxis(img, cntr, p1, new Scalar(0, 255, 0), 1);
            drawAxis(img, cntr, p2, new Scalar(255, 255, 0), 5);
            double angle = Math.Atan2(eigen_vecs[0].Y, eigen_vecs[0].X); // orientation in radians
            return angle;
        }

    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值