OpenCV Principal Component Analysis(PCA)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <cv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
 
void drawAxis(Mat &img, Point p, Point q, Scalar colour, const float scale = 0.2)
{
    double angle;
    double hypotenuse;
    angle = atan2((double)p.y - q.y, (double)p.x - q.x);
    hypotenuse = 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 * cos(angle));
    q.y = (int)(p.y - scale * hypotenuse * sin(angle));
    line(img, p, q, colour, 1, CV_AA);
 
    // create the arrow hooks
    p.x = (int)(q.x + 9 * cos(angle + CV_PI / 4));
    p.y = (int)(q.y + 9 * sin(angle + CV_PI / 4));
    line(img, p, q, colour, 1, CV_AA);
    
    p.x = (int)(q.x + 9 * cos(angle - CV_PI / 4));
    p.y = (int)(q.y + 9 * sin(angle - CV_PI / 4));
    line(img, p, q, colour, 1, CV_AA);
}
 
double getOrientation(const vector<Point> &pts, Mat &img)
{
    // construct a buffer used by the pca analysis
    int sz = static_cast<int>(pts.size());
    Mat data_pts = Mat(sz, 2, CV_64FC1);
 
    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(data_pts, Mat(), CV_PCA_DATA_AS_ROW);
 
    //Store the center of the object
    Point cntr = Point(static_cast<int>(pca_analysis.mean.at<double>(00)), 
        static_cast<int>(pca_analysis.mean.at<double>(01)));
 
    //Store and eigenvalues and eigenvectors
    vector<Point2d> eigen_vecs(2);
    vector<double> eigen_val(2);
 
    for (int i = 0; i < 2++i)
    {
        eigen_vecs[i] = Point2d(pca_analysis.eigenvectors.at<double>(i, 0),
            pca_analysis.eigenvectors.at<double>(i, 1));
 
        eigen_val[i] = pca_analysis.eigenvalues.at<double>(i, 0);
    }
 
    //Draw the principal components
    circle(img, cntr, 3, Scalar(2550255), 2);
    Point p1 = cntr + 0.02 * Point(static_cast<int>(eigen_vecs[0].x * eigen_val[0]), 
        static_cast<int>(eigen_vecs[0].y * eigen_val[0]));
    Point p2 = cntr - 0.02 * Point(static_cast<int>(eigen_vecs[1].x * eigen_val[1]), 
        static_cast<int>(eigen_vecs[1].y * eigen_val[1]));
    
    drawAxis(img, cntr, p1, Scalar(02550), 1);
    drawAxis(img, cntr, p2, Scalar(2552550), 5);
    
    // orientation in radins
    double angle = atan2(eigen_vecs[0].y, eigen_vecs[0].x);
 
    return angle;
}
 
int main()
{
    Mat src = imread("img/pca_test1.jpg");
 
    if (!src.data || src.empty())
    {
        cout << "can't not load image" << endl;
        return EXIT_FAILURE;
    }
 
    imshow("Src", src);
 
    //Convert Image to grayScale
    Mat gray;
    cvtColor(src, gray, COLOR_BGR2GRAY);
 
    // Convert image to Binary
    Mat bw;
    threshold(gray, bw, 50.255., CV_THRESH_BINARY || CV_THRESH_OTSU);
    
    // Find all the contours in the thresholded image
    vector<Vec4i> hierarchy;
    vector<vector<Point>> contours;
    findContours(bw, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
 
    for (size_t i = 0; i < contours.size(); ++i)
    {
        // Calculate the area of each contour
        double area = contourArea(contours[i]);
 
        if (area < 1e2 || 1e5 < area)
            continue;
 
        drawContours(src, contours, static_cast<int>(i), Scalar(00255), 28, hierarchy, 0);
        getOrientation(contours[i], src);
    }
 
    imshow("output", src);
    
    waitKey(0);
    return 0;
}
cs





OpenCV Scene Change Detection(장면 전환 검출)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// http://docs.opencv.org/3.0.0/d5/dc4/tutorial_video_input_psnr_ssim.html
// Base Examples : Video Input with OpenCV and similarity measurement
 
#include <cv.hpp>
#include <string>
#include <iostream>
 
using namespace std;
using namespace cv;
 
double getPSNR(const Mat& I1, const Mat& I2)
{
    Mat s1;
    absdiff(I1, I2, s1);       // |I1 - I2|
    s1.convertTo(s1, CV_32F);  // cannot make a square on 8 bits
    s1 = s1.mul(s1);           // |I1 - I2|^2
    Scalar s = sum(s1);        // sum elements per channel
    double sse = s.val[0+ s.val[1+ s.val[2]; // sum channels
 
    if (sse <= 1e-10// for small values return zero
        return 0;
    
    double mse = sse / (double)(I1.channels() * I1.total());
    double psnr = 10.0*log10((255 * 255/ mse);
    return psnr;
}
 
void merge(const Mat &m1, const Mat &m2, Mat &result)
{
    resize(result, result, Size(m1.cols + m2.cols, m1.rows));
    
    m1.copyTo(result(Rect(00, m1.cols, m1.rows)));
    m2.copyTo(result(Rect(m1.cols, 0, m2.cols, m2.rows)));
 
    putText(result, "Normal Video", cvPoint(3030),
        FONT_HERSHEY_COMPLEX_SMALL, 1.0, cvScalar(200200250), 1, CV_AA);
 
    putText(result, "Scene Change Detection", cvPoint(m1.cols + 3030),
        FONT_HERSHEY_COMPLEX_SMALL, 1.0, cvScalar(200200250), 1, CV_AA);
}
 
int main()
{
    stringstream conv;
    char c;
    int frameNum = -1// Frame counter
    double psnrV, CHANGE_DETECT_RATIO = 15.0;
    string videoPath = "video/Megamind.avi";
 
    VideoCapture cap(videoPath);
        
    // file open
    if (!cap.isOpened()) {
        cout << "Could not open video - " << videoPath << endl;
        return -1;
    }
    Size s = Size((int)cap.get(CAP_PROP_FRAME_WIDTH), (int)cap.get(CAP_PROP_FRAME_HEIGHT));
    Mat prevFrame, currFrame, changeFrame, result(s, CV_8UC3);
    
    namedWindow("Scene Change Detection");
    resizeWindow("Scene Change Detection", s.width * 2, s.height);
    
    while (1)
    {
        ++frameNum;
        cap >> currFrame;
 
        if (frameNum < 1) {
            prevFrame = currFrame.clone();
            changeFrame = currFrame.clone();
            continue;
        }
        
        if (currFrame.rows == 0 && currFrame.cols == 0)
            break;
 
        psnrV = getPSNR(prevFrame, currFrame);
        
        if (psnrV < CHANGE_DETECT_RATIO)
            changeFrame = currFrame.clone();
        
        merge(currFrame, changeFrame, result);
        imshow("Scene Change Detection", result);
 
        if (frameNum % 2 == 0)
            prevFrame = currFrame.clone();
 
        c = (char)waitKey(10);
        
        if (c == 27)
            break;
    }
 
    return 0;
}
cs




Image Segmentation with Distance Transform and Watershed Algorithm


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <cv.hpp>
#include <iostream>
 
using namespace std;
using namespace cv;
 
int DELAY_CAPTION = 1500;
char window_name[] = "Watershed Demo";
Mat src;
 
int display_caption(char *caption, Mat input);
 
int main()
{
    src = imread("img/card2.png");
 
    if (!src.data)
        return -1;
        
    display_caption("source Image", src);
 
    for (int x = 0; x < src.rows; x++) {
        for (int y = 0; y < src.cols; y++) {
            if (src.at<Vec3b>(x, y) == Vec3b(255255255)) {
                src.at<Vec3b>(x, y)[0= 0;
                src.at<Vec3b>(x, y)[1= 0;
                src.at<Vec3b>(x, y)[2= 0;
            }
        }
    }
 
    Mat kernel = (Mat_<float>(3,3<< 111,
                                      1-81,
                                      111);
 
    Mat imgLaplacian;
    Mat sharp = src;
    filter2D(sharp, imgLaplacian, CV_32F, kernel);
    src.convertTo(sharp, CV_32F);
    Mat imgResult = sharp - imgLaplacian;
 
    imgResult.convertTo(imgResult, CV_8UC3);
    imgLaplacian.convertTo(imgLaplacian, CV_8UC3);
 
    display_caption("New Sharped Image", imgResult);
    display_caption("New Sharped Image Laplacian", imgLaplacian);
 
    src = imgResult;
 
    Mat bw;
    cvtColor(src, bw, CV_BGR2GRAY);
    threshold(bw, bw, 40255, CV_THRESH_BINARY | CV_THRESH_OTSU);
 
    Mat dist;
 
    // CV_DIST_L2 = Euclidean distance
    distanceTransform(bw, dist, CV_DIST_L2, 3);
 
    normalize(dist, dist, 01., NORM_MINMAX);
    display_caption("Distance Transform Image", dist);
 
    threshold(dist, dist, .41., CV_THRESH_BINARY);
 
    Mat kernel1 = Mat::ones(33, CV_8UC1);
    dilate(dist, dist, kernel1);
    display_caption("peaks point", dist);
 
    Mat dist_8U;
    dist.convertTo(dist_8U, CV_8U);
    
    vector<vector<Point>> contours;
    findContours(dist_8U, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
 
    Mat markers = Mat::zeros(dist.size(), CV_32SC1);
 
    for (size_t i = 0; i < contours.size(); i++)
        drawContours(markers, contours, static_cast<int>(i), Scalar::all(static_cast<int>(i)+1));
 
    circle(markers, Point(55), 3, CV_RGB(255255255), -1);
    display_caption("Marker", markers * 10000);
 
    watershed(src, markers);
 
    Mat mark = Mat::zeros(markers.size(), CV_8UC1);
    markers.convertTo(mark, CV_8UC1);
    bitwise_not(mark, mark);
    
    display_caption("Markers_v2", mark);
 
    vector<Vec3b>colors;
 
    for (size_t i = 0; i < contours.size(); i++)
    {
        int b = theRNG().uniform(0255);
        int g = theRNG().uniform(0255);
        int r = theRNG().uniform(0255);
 
        colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
    }
 
    Mat dst = Mat::zeros(markers.size(), CV_8UC3);
 
    for (int i = 0; i < markers.rows; i++)
    {
        for (int j = 0; j < markers.cols; j++)
        {
            int index = markers.at<int>(i, j);
            if (index > 0 && index <= static_cast<int>(contours.size()))
                dst.at<Vec3b>(i, j) = colors[index - 1];
            else
                dst.at<Vec3b>(i, j) = Vec3b(000);
        }
    }
 
    display_caption("Final", dst);
 
    waitKey(0); 
    
    return 0;
}
 
int display_caption(char *caption, Mat input)
{
    Mat dst;
    dst = Mat::zeros(input.size(), input.type());
    
    putText(dst, caption, Point(src.cols / 4, src.rows / 2), FONT_HERSHEY_COMPLEX, 1, Scalar(255255255));
 
    imshow(window_name, dst);
    int c = waitKey(DELAY_CAPTION);
 
    if (c >= 0)
        return -1;
 
    imshow(window_name, input);
    
    c = waitKey(DELAY_CAPTION);
 
    if (c >= 0)
        return -1;
    return 0;
}
 
cs