Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // main.cpp
- // course
- //
- // Created by Эльвина Лукманова on 21.10.16.
- // Copyright © 2016 Эльвина Лукманова. All rights reserved.
- #include <iostream>
- #include <random>
- #include <cmath>
- #include <fstream>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv2/imgproc/imgproc.hpp>
- #include <armadillo>
- #include <tbb/tbb.h>
- using namespace std;
- using namespace cv;
- enum CHANNEL {
- BLUE,
- GREEN,
- RED
- };
- namespace color {
- Scalar blue = Scalar(255, 0, 0);
- Scalar green = Scalar(0, 255, 0);
- Scalar red = Scalar(0, 0, 255);
- Scalar white = Scalar(255, 255, 255);
- Scalar black = Scalar(0, 0, 0);
- auto random = []() {
- return Scalar(rand() % 255, rand() % 255, rand() % 255);
- };
- }
- //вычисление всех степеней X^pow*Y^pow как указано в статье Рудаковой страница 5 самый верх
- void count_degrees (const Point2f & input, int degree, vector<double> & output_vector) {
- for (int i = degree; i >= 0 ; i--) {
- for (int j = 0; j <= i; j++) {
- output_vector.push_back(pow(input.x, (i - j)) * pow(input.y, j));
- }
- }
- }
- void least_quadrantic (const vector<vector<double>> & input, int degree, const vector<double> & centers_green,
- vector<vector<double>> & output, vector<double> & solution) {
- int end = (degree + 1) * (degree + 2) / 2;
- for (int i = 0; i < end; i++) {
- vector<double> additional;
- for (int j = 0; j < end; j++) {
- double sum = 0;
- for (int k = 0; k < input.size(); k++) {
- sum += input[k][j] * input[k][i];
- }
- additional.push_back(sum);
- }
- output.push_back(additional);
- double sum = 0;
- for (int k = 0; k < input.size(); k++){
- sum += centers_green[k] * input[k][i];
- }
- solution.push_back(sum);
- }
- }
- Point2i solution(const arma::vec & coefficients_for_x, const arma::vec & coefficients_for_y, int degree,
- const Point2f & current_pixel_coordinate, int optical_center_x, int optical_center_y) {
- Point2f corrected_coordinate{0, 0};
- vector<double> degrees_for_x;
- vector<double> degrees_for_y;
- count_degrees(current_pixel_coordinate, degree, degrees_for_x);
- count_degrees(Point2f(current_pixel_coordinate.y, current_pixel_coordinate.x), degree, degrees_for_y);
- for (int i = 0; i < degrees_for_x.size(); i++) {
- corrected_coordinate.x += coefficients_for_x[i] * degrees_for_x[i];
- corrected_coordinate.y += coefficients_for_y[i] * degrees_for_y[i];
- }
- return {(int)(round(optical_center_x + corrected_coordinate.x)),
- (int)(round(optical_center_y - corrected_coordinate.y))};
- }
- int main() {
- //тестовый шаблон
- // unsigned int height = 1123, width = 1587;
- // Mat image(height, width, CV_8UC3, Scalar(255, 255, 255)); //генерация шаблона
- // int x = 45, y = 45, radius = 15;
- // while (x + 15 < width){
- // while (y + 15 < height) {
- // circle(image, Point(x, y), radius, Scalar(0, 0, 0), CV_FILLED, 15 );
- // y += 45;
- // }
- // y = 45;
- // x += 45;
- //
- // }
- //
- //
- // imwrite("/Users/elvinalu/Desktop/picture.jpeg", image);
- //второй тестовый шаблон -- имитация аберрации
- unsigned int height = 1600, width = 1600;
- Mat image(height, width, CV_8UC3, color::white); //генерация шаблона
- int x = 400, y = 400, radius = 150;
- while (x + radius < width) {
- while (y + radius < height) {
- circle(image, Point(x, y), radius, color::black, CV_FILLED, 15);
- y += 400;
- }
- x += 400, y = 400;
- }
- imwrite("/Users/elvinalu/Desktop/picture.jpeg", image);
- image.release();
- Mat image1 = imread ("/Users/elvinalu/Desktop/picture.jpeg", 1);
- for (int i = 0; i < 600; i++) {
- for (int j = 0; j < image1.cols; j++) {
- if (j < 600) {
- image1.at<Vec3b>(i, j)[0] = image1.at<Vec3b>(i + 3, j + 3)[0];
- } else {
- image1.at<Vec3b>(i, j)[0] = image1.at<Vec3b>(i + 3, j)[0];
- if (j > 1000) {
- image1.at<Vec3b>(i, j)[0] = image1.at<Vec3b>(i + 3, j - 3)[0];
- }
- }
- }
- }
- for (int i = 600; i < 1000; i++) {
- for (int j = 0; j < 600; j++) {
- image1.at<Vec3b>(i, j)[0] = image1.at<Vec3b>(i, j + 3)[0];
- }
- for (int j = image1.cols; j > 1000; j--) {
- image1.at<Vec3b>(i, j)[0] = image1.at<Vec3b>(i, j - 3)[0];
- }
- }
- for (int i = image1.rows - 1; i > 1000; i--) {
- for (int j = 0; j < image1.cols; j++) {
- if (j < 600) {
- image1.at<Vec3b>(i, j)[0] = image1.at<Vec3b>(i - 3, j + 3)[0];
- } else {
- image1.at<Vec3b>(i, j)[0] = image1.at<Vec3b>(i - 3, j)[0];
- if (j > 1000) {
- image1.at<Vec3b>(i, j)[0] = image1.at<Vec3b>(i - 3, j - 3)[0];
- }
- }
- }
- }
- // imwrite("/Users/elvinalu/Desktop/picture1.jpeg", image1);
- // Mat img = imread("/Users/elvinalu/Desktop/picture1.jpeg", 1); //загрузка фотографии шаблона
- // Mat imgy = imread("/Users/elvinalu/Desktop/picture1.jpeg", 1);
- Mat image2 = imread ("/Users/elvinalu/Desktop/picture.jpeg", 1);
- for (int i = 0; i < 600; i++) {
- for (int j = 0; j < image2.cols; j++) {
- if (j < 600) {
- image2.at<Vec3b>(i, j)[2] = image2.at<Vec3b>(i + 3, j + 3)[2];
- } else {
- image2.at<Vec3b>(i, j)[2] = image2.at<Vec3b>(i + 3, j)[2];
- if (j > 1000) {
- image2.at<Vec3b>(i, j)[2] = image2.at<Vec3b>(i + 3, j - 3)[2];
- }
- }
- }
- }
- for (int i = 600; i < 1000; i++) {
- for (int j = 0; j < 600; j++) {
- image2.at<Vec3b>(i, j)[2] = image2.at<Vec3b>(i ,j + 3)[2];
- }
- for (int j = image2.cols; j > 1000; j--) {
- image2.at<Vec3b>(i, j)[2] = image2.at<Vec3b>(i, j - 3)[2];
- }
- }
- for (int i = image2.rows - 1; i > 1000; i--) {
- for (int j = 0; j < image2.cols; j++) {
- if (j < 600) {
- image2.at<Vec3b>(i, j)[2] = image2.at<Vec3b>(i - 3, j + 3)[2];
- } else {
- image2.at<Vec3b>(i, j)[2] = image2.at<Vec3b>(i - 3, j)[2];
- if (j > 1000) {
- image2.at<Vec3b>(i, j)[2] = image2.at<Vec3b>(i - 3, j - 3)[2];
- }
- }
- }
- }
- imwrite("/Users/elvinalu/Desktop/picture2.jpeg", image2);
- // Mat img = imread("/Users/elvinalu/Desktop/picture2.jpeg", 1); //загрузка фотографии шаблона
- // Mat imgy = imread("/Users/elvinalu/Desktop/picture2.jpeg", 1);
- Mat img = imread("/Users/elvinalu/Desktop/IMG_0124.jpg", 1); //загрузка фотографии шаблона
- Mat imgy = imread("/Users/elvinalu/Desktop/IMG_0124.jpg", 1);
- Mat img_result(img.rows, img.cols, CV_8UC3, color::white);
- Mat img_copy(img.rows, img.cols, CV_8UC3, color::white);
- Mat imge(img.rows, img.cols, CV_8UC3, color::white);
- vector<Mat> channels;
- split(img, channels);//разбиение шаблона на каналы
- Mat red;
- Mat green;
- Mat blue;
- vector<vector<Point>> contours_red;
- vector<vector<Point>> contours_blue;
- vector<vector<Point>> contours_green;
- auto draw_contours_in_specified_channel = [&](size_t channel, Mat & color, vector<vector<Point>> & contours, string channel_name) {
- blur(channels[channel], color, Size(3, 3));
- threshold(color, color, 135, 255, THRESH_BINARY);
- findContours(color, contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
- vector<RotatedRect> min_rect(contours.size());
- vector<RotatedRect> min_ellipse;
- for (int i = 0; i < contours.size(); i++) {
- min_rect[i] = minAreaRect(Mat(contours[i]));
- if (contours[i].size() > 5 && min_rect[i].size.width > 15.0) {
- min_ellipse.push_back(fitEllipse(Mat(contours[i])));
- }
- }
- for (int i = 0; i < min_ellipse.size(); i++) {
- auto contour_color = color::random();
- drawContours(imge, contours, i, contour_color, 1, 8, vector<Vec4i>(), 0, Point());
- ellipse(img_copy, min_ellipse[i], contour_color, 2, 8);
- Point2f rect_points[4];
- min_rect[i].points(rect_points);
- for (int j = 0; j < 4; j++) {
- line(imge, rect_points[j], rect_points[(j + 1) % 4], contour_color, 1, 8);
- }
- }
- imwrite("/Users/elvinalu/Desktop/" + channel_name + ".jpg", color);
- return min_ellipse;
- };
- auto min_ellipse_red = draw_contours_in_specified_channel(CHANNEL::RED, red, contours_red, "red");
- auto min_ellipse_blue = draw_contours_in_specified_channel(CHANNEL::BLUE, blue, contours_blue, "blue");
- auto min_ellipse_green = draw_contours_in_specified_channel(CHANNEL::GREEN, green, contours_green, "green");
- cout << min_ellipse_red.size() << ' ' << min_ellipse_blue.size() << ' ' << min_ellipse_green.size() << endl;
- auto calculate_distortion = [&](vector<RotatedRect> & min_ellipse, Scalar color) {
- for (int i = 0; i < min_ellipse_green.size(); i++) {
- for (int j = 0; j < min_ellipse.size(); j++) {
- if (abs(min_ellipse_green[i].center.x - min_ellipse[j].center.x) < 10 &&
- abs(min_ellipse_green[i].center.y - min_ellipse[j].center.y) < 10 && i!=j) {
- swap(min_ellipse[j], min_ellipse[i]);
- break;
- }
- }
- Point distortion = (min_ellipse[i].center - min_ellipse_green[i].center) * 15;
- line(imge, (Point)min_ellipse_green[i].center, (Point)min_ellipse[i].center + distortion, color, 3);
- circle(imge, (Point)min_ellipse_green[i].center, 1, color::green, CV_FILLED, 15);
- }
- };
- calculate_distortion(min_ellipse_red, color::red);
- calculate_distortion(min_ellipse_blue, color::blue);
- // работа с центрами и их перевод в локальную систему относительно центров эллипсов в зеленом канале
- imwrite("/Users/elvinalu/Desktop/picture0.jpeg", imge);
- vector <Point2f> centers_red (min_ellipse_red.size());
- vector <double> centers_green_X (min_ellipse_green.size());
- vector <double> centers_green_Y (min_ellipse_green.size());
- vector <Point2f> centers_blue (min_ellipse_blue.size());
- float min_blue_distortion_x = 10, min_blue_distortion_y = 10, min_red_distortion_x = 10, min_red_distortion_y = 10;
- int key = 0;
- for (int i = 0; i < min_ellipse_green.size(); i++) {
- if ((abs(min_ellipse_green[i].center.x - min_ellipse_blue[i].center.x) <= min_blue_distortion_x) &&
- (abs(min_ellipse_green[i].center.y - min_ellipse_blue[i].center.y) <= min_blue_distortion_y) &&
- (abs(min_ellipse_green[i].center.x - min_ellipse_red[i].center.x) <= min_red_distortion_x) &&
- (abs(min_ellipse_green[i].center.y - min_ellipse_red[i].center.y) <= min_red_distortion_y))
- {
- min_red_distortion_x = abs (min_ellipse_green[i].center.x - min_ellipse_red[i].center.x);
- min_blue_distortion_x = abs(min_ellipse_green[i].center.x - min_ellipse_blue[i].center.x);
- min_blue_distortion_y = abs(min_ellipse_green[i].center.y - min_ellipse_blue[i].center.y);
- min_red_distortion_y = abs(min_ellipse_green[i].center.y - min_ellipse_red[i].center.y);
- key = i;
- }
- }
- Point2i optical_center = Point2i(round(min_ellipse_green[key].center.x), round(min_ellipse_green[key].center.y));
- auto coordinate_transition = [](vector<Point2f> & centers, const vector<RotatedRect> & min_ellipse, const Point2f & optical_center) {
- for (int i = 0; i < min_ellipse.size(); i++) {
- centers[i].x = (min_ellipse[i].center.x - optical_center.x);
- centers[i].y = (optical_center.y - min_ellipse[i].center.y);
- }
- };
- coordinate_transition(centers_red, min_ellipse_red, optical_center);
- coordinate_transition(centers_blue, min_ellipse_red, optical_center);
- for (int i = 0; i < min_ellipse_green.size(); i++) {
- centers_green_X[i] = (min_ellipse_green[i].center.x - optical_center.x);
- centers_green_Y[i] = (optical_center.y - min_ellipse_green[i].center.y);
- }
- int Degree = 1;
- vector<vector<double>> red_Xy(centers_red.size());
- vector<vector<double>> blue_Xy(centers_blue.size());
- vector<vector<double>> blue_xY(centers_blue.size());
- vector<vector<double>> red_xY(centers_red.size());
- tbb::parallel_for(int(0), (int)centers_red.size(), [&](int i) {
- count_degrees(centers_red[i], Degree, red_Xy[i]);
- count_degrees(centers_blue[i], Degree, blue_Xy[i]);
- count_degrees(Point2f(centers_red[i].y, centers_red[i].x), Degree, red_xY[i]);
- count_degrees(Point2f(centers_blue[i].y, centers_blue[i].x), Degree, blue_xY[i]);
- });
- //запись вывода в файл
- ofstream out ("/Users/elvinalu/Desktop/test1.txt");
- out << scientific;
- out.precision(1);
- int end = (Degree + 1) * (Degree + 2) / 2;
- for (int i = 0; i < centers_red.size(); i++) {
- for (int j = 0; j < end; j++) {
- if (j != end - 1) {
- out <<"p[" << i << "][" << j << "]*" << blue_Xy[i][j] << "+ ";
- } else {
- out <<"p[" << i << "][" << j << "]*" << blue_Xy[i][j] << " = " << centers_green_X[i];
- }
- }
- out << endl;
- }
- out.close();
- vector<vector<double>> DegreeX_yRed;
- vector<vector<double>> DegreeX_yBlue;
- vector<double> solve_green_RedX;
- vector<double> solve_green_BlueX;
- vector<vector<double>> Degreex_YRed;
- vector<vector<double>> Degreex_YBlue;
- vector<double> solve_green_RedY;
- vector<double> solve_green_BlueY;
- least_quadrantic(red_Xy, Degree, centers_green_X, DegreeX_yRed, solve_green_RedX);
- least_quadrantic(blue_Xy, Degree, centers_green_X, DegreeX_yBlue, solve_green_BlueX);
- least_quadrantic(red_xY, Degree, centers_green_Y, Degreex_YRed, solve_green_RedY);
- least_quadrantic(blue_xY, Degree, centers_green_Y, Degreex_YBlue, solve_green_BlueY);
- //запись вывода в файл для наглядности + создание дополнительных матриц для решения системы ЛУ в armadillo
- ofstream fout ("/Users/elvinalu/Desktop/test2.txt");
- fout << scientific;
- fout.precision(1);
- arma::mat redx = arma::Mat<double>(DegreeX_yRed.size(), DegreeX_yRed.size());
- arma::mat bluex = arma::Mat<double>(DegreeX_yBlue.size(), DegreeX_yBlue.size());
- arma::mat redy = arma::Mat<double>(Degreex_YRed.size(), Degreex_YRed.size());
- arma::mat bluey = arma::Mat<double>(Degreex_YBlue.size(), Degreex_YBlue.size());
- for (int i = 0; i < DegreeX_yRed.size(); i++) {
- for (int j = 0; j < DegreeX_yRed.size(); j++) {
- redx(i, j) = DegreeX_yRed[i][j];
- bluex(i, j) = DegreeX_yBlue[i][j];
- redy(i, j) = Degreex_YRed[i][j];
- bluey(i, j) = Degreex_YBlue[i][j];
- if (j != end - 1) {
- fout << DegreeX_yRed[i][j] << "+ ";
- } else {
- fout << DegreeX_yRed[i][j] << " = 0";
- }
- }
- fout << endl;
- }
- fout.close();
- cout << endl << optical_center << endl;
- arma::vec solrgx = arma::solve(redx, move(arma::vec(solve_green_RedX)));
- arma::vec solbgx = arma::solve(bluex, move(arma::vec(solve_green_BlueX)));
- arma::vec solrgy = arma::solve(redy, move(arma::vec(solve_green_RedY)));
- arma::vec solbgy = arma::solve(bluey, move(arma::vec(solve_green_BlueY)));
- solrgx.print();
- cout << endl << endl;
- solrgy.print();
- cout << endl << endl;
- solbgx.print();
- cout << endl;
- solbgy.print();
- double maxi = 0, maxj = 0;
- double maxi1 = 0, maxj1 = 0;
- //_____________________________________
- //
- //ЗДЕСЬ ТЕСТОВАЯ РАСПЕЧАТКА МАКСИМАЛЬНЫХ ОТКЛОНЕНИЙ В КРАСНОМ КАНАЛЕ ДЛЯ УЖЕ САППРОКСИМИРОВАННЫХ ЗНАЧЕНИЙ!!!
- //
- //_____________________________________
- for (int t = 0; t < centers_red.size(); t++) {
- Point2i coord_red = solution(solrgx, solrgy, Degree, Point2f(centers_red[t].x,centers_red[t].y), optical_center.x, optical_center.y);
- if (maxi < abs(min_ellipse_green[t].center.x - coord_red.x)) {
- maxi = abs(min_ellipse_green[t].center.x - coord_red.x);
- }
- if (maxj < abs(min_ellipse_green[t].center.y - coord_red.y)) {
- maxj = abs(min_ellipse_green[t].center.y - coord_red.y);
- }
- cout << min_ellipse_red[t].center << "; " << min_ellipse_green[t].center << endl;
- cout << coord_red << "; [" << centers_green_X[t] << "; " << centers_green_Y[t] << "];" << endl;
- cout << endl << endl;
- if (maxi1 < abs(centers_green_X[t] - centers_red[t].x)) {
- maxi1 = abs(centers_green_X[t] - centers_red[t].x);
- }
- if (maxj1 < abs(centers_green_Y[t]- centers_red[t].y)) {
- maxj1 = abs(centers_green_Y[t] - centers_red[t].y);
- }
- }
- //новое максимальное отклонение
- cout << maxi << " " << maxj << endl;
- //старое
- cout << maxi1 << " " << maxj1 << endl;
- cout << endl << endl << endl;
- double maxbi = 0, maxbj = 0;
- double maxib1 = 0, maxjb1 = 0;
- for (int t = 0; t < centers_blue.size(); t++) {
- Point2i coord_blue = solution(solbgx, solbgy, Degree, Point2f(centers_blue[t].x,centers_blue[t].y), optical_center.x, optical_center.y);
- if (maxbi < abs(min_ellipse_green[t].center.x - min_ellipse_blue[t].center.x)) {
- maxbi = abs(min_ellipse_green[t].center.x - min_ellipse_blue[t].center.x);
- }
- if (maxbj < abs(min_ellipse_green[t].center.y - min_ellipse_blue[t].center.y)) {
- maxbj = abs(min_ellipse_green[t].center.y - min_ellipse_blue[t].center.y);
- }
- cout << min_ellipse_blue[t].center << "; " << min_ellipse_green[t].center << endl;
- cout << coord_blue << "; " << min_ellipse_green[t].center << endl;
- cout << endl << endl;
- if (maxib1 < abs(centers_green_X[t] - centers_blue[t].x)) {
- maxib1 = abs(centers_green_X[t] - centers_blue[t].x);
- }
- if (maxjb1 < abs(centers_green_Y[t]- centers_blue[t].y)) {
- maxjb1 = abs(centers_green_Y[t] - centers_blue[t].y);
- }
- }
- //новое максимальное отклонение
- cout << maxbi << " " << maxbj << endl;
- //старое
- cout << maxib1 << " " << maxjb1 << endl;
- imshow("img2", imgy);
- imwrite("/Users/elvinalu/Desktop/picture3.jpeg", imgy);
- tbb::tick_count t0 = tbb::tick_count().now();
- tbb::parallel_for(int(0), img.rows, [&](int i) {
- tbb::parallel_for(int(0), img.cols, [&](int j) {
- Point2i coord_red = solution(solrgx, solrgy, Degree, Point2f(i - optical_center.x,optical_center.y - j), optical_center.x, optical_center.y);
- Point2i coord_blue = solution(solbgx, solbgy, Degree, Point2f(i - optical_center.x,optical_center.y - j), optical_center.x, optical_center.y);
- //solution(solbgx, solbgy, Degree, Point2f(centers_blue[t].x,centers_blue[t].y), optical_center.x, optical_center.y)
- //img_result.at<Vec3b>(i, j)[2] = imgy.at<Vec3b> (i, j)[2];
- img_result.at<Vec3b>(i, j)[1] = imgy.at<Vec3b>(i, j)[1];
- //img_result.at<Vec3b>(i, j)[0] = imgy.at<Vec3b>(i,j)[0];
- img_result.at<Vec3b>(coord_blue.x, coord_blue.y)[0] = imgy.at<Vec3b>(i, j)[0];
- img_result.at<Vec3b>(coord_red.x, coord_red.y)[2] = imgy.at<Vec3b>(i, j)[2];
- if (i == 397 && ((j > 396 && j < 401) || (j > 798 && j < 802))) {
- printf(" %d; %d\t\t%.0d; %.0d\n", i, j, coord_blue.x, coord_blue.y);
- }
- });
- });
- tbb::tick_count t1 = tbb::tick_count().now();
- cout << (t1 - t0).seconds() << endl;
- cout << "end" ;
- imshow("img_result", img_result);
- imwrite("/Users/elvinalu/Desktop/pictr.jpeg", img_result);
- image.release();
- red.release();
- green.release();
- blue.release();
- img.release();
- imge.release();
- imgy.release();
- img_copy.release();
- img_result.release();
- image1.release();
- image2.release();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement