1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4
5 #include "precomp.hpp"
6 #include "intraU.hpp"
7
8 namespace cv { namespace alphamat {
9
findColMajorInd(int rowMajorInd,int nRows,int nCols)10 int findColMajorInd(int rowMajorInd, int nRows, int nCols)
11 {
12 int iInd = rowMajorInd / nCols;
13 int jInd = rowMajorInd % nCols;
14 return (jInd * nRows + iInd);
15 }
16
17 static
generateFVectorIntraU(my_vector_of_vectors_t & samples,Mat & img,Mat & tmap,std::vector<int> & orig_ind)18 void generateFVectorIntraU(my_vector_of_vectors_t& samples, Mat& img, Mat& tmap, std::vector<int>& orig_ind)
19 {
20 int nRows = img.rows;
21 int nCols = img.cols;
22 int unk_count = 0;
23 int i, j;
24 for (i = 0; i < nRows; ++i)
25 {
26 for (j = 0; j < nCols; ++j)
27 {
28 uchar pix = tmap.at<uchar>(i, j);
29 if (pix == 128)
30 unk_count++;
31 }
32 }
33 samples.resize(unk_count);
34 orig_ind.resize(unk_count);
35
36 int c1 = 0;
37 for (i = 0; i < nRows; ++i)
38 {
39 for (j = 0; j < nCols; ++j)
40 {
41 uchar pix = tmap.at<uchar>(i, j);
42 if (pix == 128) // collection of unknown pixels samples
43 {
44 samples[c1].resize(ALPHAMAT_DIM);
45 samples[c1][0] = img.at<cv::Vec3b>(i, j)[0] / 255.0;
46 samples[c1][1] = img.at<cv::Vec3b>(i, j)[1] / 255.0;
47 samples[c1][2] = img.at<cv::Vec3b>(i, j)[2] / 255.0;
48 samples[c1][3] = (double(i + 1) / nRows) / 20;
49 samples[c1][4] = (double(j + 1) / nCols) / 20;
50 orig_ind[c1] = i * nCols + j;
51 c1++;
52 }
53 }
54 }
55
56 CV_LOG_INFO(NULL, "ALPHAMAT: Total number of unknown pixels : " << c1);
57 }
58
59 static
kdtree_intraU(Mat & img,Mat & tmap,my_vector_of_vectors_t & indm,my_vector_of_vectors_t & samples,std::vector<int> & orig_ind)60 void kdtree_intraU(Mat& img, Mat& tmap, my_vector_of_vectors_t& indm, my_vector_of_vectors_t& samples, std::vector<int>& orig_ind)
61 {
62 // Generate feature vectors for intra U:
63 generateFVectorIntraU(samples, img, tmap, orig_ind);
64
65 typedef KDTreeVectorOfVectorsAdaptor<my_vector_of_vectors_t, double> my_kd_tree_t;
66 my_kd_tree_t mat_index(ALPHAMAT_DIM /*dim*/, samples, 10 /* max leaf */);
67 mat_index.index->buildIndex();
68 // do a knn search with ku = 5
69 const size_t num_results = 5 + 1;
70
71 int N = samples.size(); // no. of unknown samples
72
73 std::vector<size_t> ret_indexes(num_results);
74 std::vector<double> out_dists_sqr(num_results);
75 nanoflann::KNNResultSet<double> resultSet(num_results);
76
77 indm.resize(N);
78 for (int i = 0; i < N; i++)
79 {
80 resultSet.init(&ret_indexes[0], &out_dists_sqr[0]);
81 mat_index.index->findNeighbors(resultSet, &samples[i][0], nanoflann::SearchParams(10));
82
83 indm[i].resize(num_results - 1);
84 for (std::size_t j = 1; j < num_results; j++)
85 {
86 indm[i][j - 1] = ret_indexes[j];
87 }
88 }
89 }
90
91 static
l1norm(std::vector<double> & x,std::vector<double> & y)92 double l1norm(std::vector<double>& x, std::vector<double>& y)
93 {
94 double sum = 0;
95 for (int i = 0; i < ALPHAMAT_DIM; i++)
96 sum += abs(x[i] - y[i]);
97 return sum / ALPHAMAT_DIM;
98 }
99
100 static
intraU(Mat & img,my_vector_of_vectors_t & indm,my_vector_of_vectors_t & samples,std::vector<int> & orig_ind,SparseMatrix<double> & Wuu,SparseMatrix<double> & Duu)101 void intraU(Mat& img, my_vector_of_vectors_t& indm, my_vector_of_vectors_t& samples,
102 std::vector<int>& orig_ind, SparseMatrix<double>& Wuu, SparseMatrix<double>& Duu)
103 {
104 // input: indm, samples
105 int n = indm.size(); // num of unknown samples
106 CV_LOG_INFO(NULL, "ALPHAMAT: num of unknown samples, n : " << n);
107
108 int i, j, nbr_ind;
109 for (i = 0; i < n; i++)
110 {
111 samples[i][3] *= 1 / 100;
112 samples[i][4] *= 1 / 100;
113 }
114
115 my_vector_of_vectors_t weights;
116 typedef Triplet<double> T;
117 std::vector<T> triplets, td;
118
119 double weight;
120 for (i = 0; i < n; i++)
121 {
122 int num_nbr = indm[i].size();
123 int cMaj_i = findColMajorInd(orig_ind[i], img.rows, img.cols);
124 for (j = 0; j < num_nbr; j++)
125 {
126 nbr_ind = indm[i][j];
127 int cMaj_nbr_j = findColMajorInd(orig_ind[nbr_ind], img.rows, img.cols);
128 weight = max(1 - l1norm(samples[i], samples[j]), 0.0);
129
130 triplets.push_back(T(cMaj_i, cMaj_nbr_j, weight / 2));
131 td.push_back(T(cMaj_i, cMaj_i, weight / 2));
132
133 triplets.push_back(T(cMaj_nbr_j, cMaj_i, weight / 2));
134 td.push_back(T(cMaj_nbr_j, cMaj_nbr_j, weight / 2));
135 }
136 }
137
138 Wuu.setFromTriplets(triplets.begin(), triplets.end());
139 Duu.setFromTriplets(td.begin(), td.end());
140 }
141
UU(Mat & image,Mat & tmap,SparseMatrix<double> & Wuu,SparseMatrix<double> & Duu)142 void UU(Mat& image, Mat& tmap, SparseMatrix<double>& Wuu, SparseMatrix<double>& Duu)
143 {
144 my_vector_of_vectors_t samples, indm;
145 std::vector<int> orig_ind;
146
147 kdtree_intraU(image, tmap, indm, samples, orig_ind);
148 intraU(image, indm, samples, orig_ind, Wuu, Duu);
149 CV_LOG_INFO(NULL, "ALPHAMAT: Intra U Done");
150 }
151
152 }} // namespace cv::alphamat
153