Страницы

Поиск по вопросам

вторник, 23 апреля 2019 г.

Makefile для отдельных каталогов src и bin

Существует дерево файлов:
folder |-src |-myfile.cpp |-myfile.h |-bin |-Makefile
Хочу написать Makefile так, чтобы компилировались файлы, находящиеся в каталоге src, но объектные файлы создавались в текущем (в folder). А потом, чтобы они линковались в один файл в каталог bin.
На данный момент имею нерабочий Makefile. Ругается на отсутствие правила для myfile.o.
TARGET=myfile OBJECTS=myfile.o XX=g++ CXXFLAGS=-std=c++11
all: ${TARGET} ${TARGET}: ${OBJECTS} ${XX} -o ${TARGET} ${OBJECTS} .c.o: ${XX} ${CXXFLAGS} -c "${INCLUDE}$<" -o "$@"
Как правильно реализовать поставленную задачу?


Ответ

чтобы они линковались в один файл в каталог bin
значит, собирать вам надо не myfile, а bin/myfile. это я про переменную TARGET
объектные файлы создавались в текущем
так и укажите цель и пререквизиты соответствующим образом:
%.o: src/%.cpp $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $(OUTPUT_OPTION) $<
здесь вторая строка, рецепт, взята из implicit rules, которые можно посмотреть в выводе команды make -p

остаётся только объяснить компилятору, где искать заголовочный файл myfile.h (если, конечно, компилятор сам не «догадается»). тут я, как не-программист, вряд ли чем помогу. разве что предположу, что надо добавить к значению перменной CPPFLAGS или CXXFLAGS опцию -I src

Как рассчитать радиус?

Извиняюсь за название, просто я не знаю как назвать тему. Дело вот какое.. Представьте что у Вас в руках равносторонний-прямой угол и плоскость, на которой одной стороной лежит этот угол. Теперь найдите мнимый центр и поверните этот угол так, чтобы вторая его сторона заняла место первой. Понимаю что не понятно поэтому иллюстрация ниже.

Когда я поверну угол на 90 градусов вокруг точки O, то отрезок CA займет место отрезка AB.
Теперь представьте что угол 45 градусов.

Как мне найти длину радиуса OE чтобы отложив от отрезка AB перпендикуляр равной длины, я нашел точку, повернув угол вокруг которой на 45 градусов я поместил отрезок CA в положение AB?


Ответ

Если я правильно понял условие, то точку O надо поместить в точку пересечения биссектрисы угла BAC и срединного перпендикуляра к отрезку AB.
В общем, равнобедренный треугольник AOB с основанием AB, угол OAB равен половине угла BAC. Надо найти высоту. Для этого есть несколько способов разной сложности.

Обнаружение зон при использовании порога

Имею изображение после использования порога: Вопрос в обнаружении белых зон: 1) Используя многоугольник (который рисует пользователь (хотелось бы еще узнать как рисовать на Mat)) и узнавать процент закрашенности внутри этой зоны 2) Автоматически (рисуя вокруг зон квадраты) Любой из двух вариантов подойдет.
Дополнение Для внесения ясности попытался сфотошопить то, чтобы я хотел получить.
Попробовав так, получил краш при использовании FindContours (баг EmguCV или моя ошибка?)
using (Mat hirarchy = new Mat()) { using (VectorOfPoint countours = new VectorOfPoint()) { CvInvoke.FindContours(_diffMat, countours, hirarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
for (int i = 0; i < countours.Size; i++) { CvInvoke.DrawContours(_diffMat, countours, i, new MCvScalar(0,0,255)); } } }


Ответ

Лучше начать, наверное, сразу со второго пункта, так как могу предположить, что именно он является приоритетным.
Бинаризация (пороговая обработка) - это по сути процесс, при котором количество информации, имеющейся на изображении, сводится к минимуму. Этот факт является одновременно и плюсом и минусом, поскольку вместе с непредставляющей интереса информацией стирается и та, что могла бы существенно помочь в решении задачи.
Если обратиться к изображению с "фотошопом" и в частности к некоторым из многоугольников по центру, границы которых отмечены красными линиями, то не трудно заметить наличие с правой стороны от них белых "зон". Эти "зоны" имеют тот же размер и в целом никак не выделяются от точно таких же белых "зон", но уже входящих в области интереса (парковочные места).
Белые "зоны" внутри области интереса также могут иметь произвольный размер и часто их нельзя рассматривать как единое целое с другими, расположенными неподалёку, поскольку они имеют самостоятельные границы и относительно близкий размер с теми, что не входят в область интереса.
Ко всему прочему, "зоны" между двумя областями интереса могут находиться ближе друг другу (по расстоянию между центральными моментами контуров), нежели чем "зоны" одного и того же парковочного места.
Все вышеперечисленные исключения в полной мере представлены на изображении "фотошопа", что фактически сводит на нет возможность корректной кластеризации контуров "зон" в объекты "автомобиль".
При помощи бинаризации чрезвычайно редко удаётся получить приемлемый результат, если исходное изображение содержит естественную среду.
Однако, если допустить вмешательство человека в работу алгоритма, а именно подсказать последнему настоящие границы объекта путём ручного выделения прямоугольников парковочных мест, то вся задача сведётся к достаточно простой операции. Пример бинаризации изображения на C++ и C# (EmguCV).
Предположим, имеется исходник:

Загружаем его, переводим в оттенки серого и бинаризуем:
C++:
cv::Mat src_mat = cv::imread("img.jpg"); if(src_mat.empty()) return;
cv::Mat gry_mat; cv::cvtColor(src_mat, gry_mat, cv::COLOR_BGR2GRAY);
cv::Mat bin1_mat, bin2_mat; cv::threshold(gry_mat, bin1_mat, 230, 255, cv::THRESH_BINARY); cv::threshold(gry_mat, bin2_mat, 25, 255, cv::THRESH_BINARY_INV); cv::Mat bin_mat = bin1_mat + bin2_mat;
C#:
Mat srcMat = new Mat("img.jpg", LoadImageType.AnyColor); if(srcMat.IsEmpty) return;
Mat grayMat = new Mat(); Mat bin1Mat = new Mat(); Mat bin2Mat = new Mat(); Mat binMat = new Mat();
CvInvoke.CvtColor(srcMat, grayMat, ColorConversion.Bgr2Gray); CvInvoke.Threshold(grayMat, bin1Mat, 230, 255, ThresholdType.Binary); CvInvoke.Threshold(grayMat, bin2Mat, 25, 255, ThresholdType.BinaryInv); CvInvoke.Add(bin1Mat, bin2Mat, binMat);
Здесь выполнена попытка бинаризации по верхней и нижней границам. Коэффициенты подобраны вручную и могут отличаться по оптимальности для других изображений. Таким образом получается сохранить больше полезных деталей:

Далее, если мы начнём искать контуры и нарисуем их:
C++:
std::vector > contours; cv::findContours(bin_mat.clone(), contours , cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
cv::Mat ctr_mat = cv::Mat::zeros(bin_mat.size(), CV_8U); cv::drawContours(ctr_mat, contours, -1, cv::Scalar::all(255), 1);
C#:
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); Mat hierarchy;
CvInvoke.FindContours(binMat, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxSimple);
Mat ctrMat = new Mat(binMat.Size, DepthType.Cv8U, 3); CvInvoke.DrawContours(ctrMat, contours, -1, new MCvScalar(255));
... то получим такую картину:

Контуров оказалось довольно много, и уже закрадывается сомнение в том, что удастся собрать контуры отдельных частей в единый контур автомобиля. Попробуем отфильтровать часть из них, например, по площади, заодно нарисовав их опоясывающие "квадратики" на исходном изображении:
C++:
std::vector > contours; cv::findContours(bin_mat.clone(), contours , cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
std::vector > contours2; for(auto itr = contours.begin(); itr != contours.end(); ++itr) { if(cv::contourArea(*itr) > 8) { contours2.push_back(*itr);
cv::Rect rc = cv::boundingRect(*itr); cv::rectangle(src_mat, rc, cv::Scalar(0,0,255)); } }
cv::Mat ctr_mat = cv::Mat::zeros(bin_mat.size(), CV_8U); cv::drawContours(ctr_mat, contours2, -1, cv::Scalar::all(255), 1);
C#:
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); VectorOfVectorOfPoint contours2 = new VectorOfVectorOfPoint(); Mat hierarchy;
CvInvoke.FindContours(binMat, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxSimple);
for (int i = 0; i < contours.Size; ++i) { if (CvInvoke.ContourArea(contours[i]) > 8) { contours2.Push(contours[i]);
Rectangle rc = CvInvoke.BoundingRectangle(contours[i]); CvInvoke.Rectangle(srcMat, rc, new MCvScalar(0, 0, 255)); } }
Mat ctrMat = new Mat(binMat.Size, DepthType.Cv8U, 3); CvInvoke.DrawContours(ctrMat, contours2, -1, new MCvScalar(255));
Контуров стало значительно меньше, "шума" поубавилось, но мы тем самым продолжаем терять информацию и об объектах интереса (автомобилях), делая их в итоге всё более непохожими на исходные. Те, что расположены поближе к камере, ещё куда ни шло, но чем дальше, тем ситуация становится плачевнее:

В конце концов, может быть стоит нарисовать опоясывающие контуры прямоугольники, и тогда станет видно, за что возможно было бы зацепиться с тем, чтобы объединить разрозненные части каждого автомобиля в единое целое:

Но ракурс съёмки не позволяет усомниться: части различных объектов расположены на относительно тех же расстояниях, что части одного и того же объекта, приводя к невозможности корректной кластеризации. А поскольку при бинаризации у нас других факторов, за которые возможно было бы зацепиться, попросту нет, то и задача с автоматическим определением границ автомобилей в имеющихся условиях становится нерешаемой. Ну может быть получится один-два автомобиля, находящихся ближе всего к камере, но не более.
В таком случае не остаётся ничего более, как вручную определить границы парковочных мест. Эту задачу на OpenCV обычно не перекладывают, т.к. у него функционал работы с мышью (с тем, чтобы пользователь указал на изображении координаты точек многоугольников парковочных мест) в целом ограничен и реализуют при помощи фреймворков общего назначения.
Для получения матрицы изображения парковочного места из заранее определённых координат в кадре можно воспользоваться простой конструкцией:
cv::Mat parking_lot_mat = src_mat(cv::Rect(0,0,100,100)).clone();
Теперь parking_lot_mat будет содержать часть исходного изображения по координатам x, равное 0, и y, равное 0, и будет размером 100х100 пикселей.
Далее производим всю ту же работу по бинаризации, что делали над большим изображением. Под конец останется найти контуры и их площади при помощи метода: cv::contourArea(). Если сумма площадей контуров превышает некий порог, вычисленный эмпирически, то значит автомобиль на данном парковочном месте можно считать обнаруженным.

Запуск Java приложений без консоли!

Начал изучать Java, до этого был опыт в Python. В Python я мог написать код сохранить в файл с расширением .py и просто запускать его. В Java же так не получается, нужно только использовать cmd или терминал в Linux для запуска файлов с кодом. Но и запуск просто файла, не достаточно, хочется например, написать какое-то пусть пока даже консольное приложение и передать кому-то ради интереса, но тупо будет просить человека запускать его через консоль. Как можно запаковать файлы например в .exe ?


Ответ

Вообще, если есть такое желание упаковывать java программу в exe, надо задуматься, тот ли язык вы выбрали?
Но если отвечать на ваш вопрос, то можно:
Собрать exe с помощью:
http://www.excelsior-usa.com/resources.html http://launch4j.sourceforge.net/ Запаковать программу в jar (имплементировав логику консольного прерывания, например, через Scanner, чтобы программа после исполнения не закрылась) Запаковать программу в jar и написать .bat файл примерно со следукщим кодом: java -jar youApp.jar pause

Доступ к серверу из интернета

На моем компьютере стоит ubuntu 14 с LAMP сервером, комп выходит в интернет через роутер при подключении WiFi, у меня есть еще и второй комп с виндой, он также выходит в интернет через тот самый роутер, но уже подключен к роутеру через шнурок. Когда я на втором компе обращаюсь к своему серверу, все работает, ftp, ssh и phpmyadmin, в общем, все гут.
Вот теперь хочу, чтобы к моему серверу можно было подключиться из интернета.
Как такое реализовать?


Ответ

нужен внешний ip-адрес (ipv4, разумеется), который может предоставить вам ваш интернет-провайдер. бесплатно или за деньги. нужно настроить ваш маршрутизатор, чтобы он внешние обращения на нужные вам порты (или вообще все внешние обращения) переадресовывал на тот из ваших компьютеров, который будет эти обращения обрабатывать. смотрите инструкцию по эксплуатации вашего маршрутизатора. как правило, никаких изменений в конфигурации компьютеров не требуется.

другие вопросы на ru.so со схожей тематикой:
Как прокинуть IP-адрес через роутер? Доступ к серверу по внешнему IP через роутер Настройка доступа к сайту извне Поднять сервер дома в денвере через роутер D-link dir400 Настройка роутера TrendNet Проброс портов на роутере TP-Link 940N Как настроить доступ к web-серверу в локальной сети? Как присвоить ститичный ip адрес компьютеру в wifi? Как узнать к какому компьютеру подключится клиент? Подключение к веб-серверу из глобальной сети

разрешение аппаратного таймера

С помощью команды в терминале powercfg -energy duration 5 узнал величину разрешение аппаратного таймера: 15,6 мс. В моих программах требуется, чтобы эта величина равнялась 1 мс. Как этого добиться при запуске программы? Для программирования пользуюсь Visual Studio 2013\2015, язык C++
PS Замечания к ответу от avp: вот тут я уже задавал вопрос про таймеры и многие попробовал. Поскольку работал с сетью, то отслеживал еще и через wireshark время пакетов отправленных с помощью таймеров. Результат оказывался плачевным.


Ответ

Возможно, функции timeBeginPeriod и timeEndPeriod (MSDN) это то что вам нужно. С их помощью, вы как раз сможете выставить желаемую точность в 1мс.

jquery drag and drop связи

Что хочу получить:
Картинка для визуализации. Задача состоит в том что бы связывать блоки (динамически протянуть стрелку от одного блок к другому) и в конце получить структуру для дальнейшей работы. Например:
a link to b
b link to c
Так же у одного блок может быть несколько связей. Прошу подсказать направление, как сделать связи.
перетаскивания сделал так:
jQuery UI Draggable - Default functionality

Drag me


Drag me



Ответ

Рабочий вариант, но код не в лучшем виде. Ссылка на plunker.
"use strict"; var can = $("#can").get(0), ctx = can.getContext('2d'); var boxes = []; function get_box(x, y) { for (var box of boxes) { if (x >= box.x && x < box.x + box.w && y >= box.y && y < box.y + box.h) { return box; } } return null; } function getxy(e) { return {x:e.clientX, y:e.clientY}; } class Box { constructor(x, y, w, h) { this.x = x; this.y = y; this.w = w; this.h = h; this.drag = null; this.name = String.fromCharCode("A".charCodeAt() + boxes.length); boxes.push(this); } on_mouse_down(e) { this.drag = { oldx: this.x, oldy: this.y, // old position of box msx: e.clientX, msy: e.clientY // mouse start x, y }; } on_mouse_move(e) { if (!this.drag) return; var dx = e.clientX - this.drag.msx, dy = e.clientY - this.drag.msy; this.x = this.drag.oldx + dx; this.y = this.drag.oldy + dy; draw_boxes(); } on_mouse_up(e) { this.drag = null; } draw() { ctx.save(); ctx.fillRect(this.x, this.y, this.w, this.h); ctx.font = "30px Georgia"; ctx.fillStyle = "white"; ctx.fillText(this.name, this.x + 10, this.y + 30); ctx.restore(); } center() { return {x: this.x + Math.floor(this.w/2), y: this.y + Math.floor(this.h/2) }; } } var link = null, links = []; function on_mouse_event(method_name) { return function (e) { for (var box of boxes) box[method_name](e); } } $("#can").mousedown(function (e) { var p = getxy(e), b = get_box(p.x, p.y); if (e.shiftKey) { new Box(p.x, p.y, 50, 50); draw_all(); return; } if (!b) return; if (e.ctrlKey) { link = {b}; return; } get_box(p.x, p.y).on_mouse_down(e); }); $("#can").mousemove((e) => { if (link) { link.t = getxy(e); } else { for (var box of boxes) box.on_mouse_move(e); } draw_all(); }); $("#can").mouseup((e) => { var x = e.clientX, y = e.clientY, b = get_box(x, y); if (link) { if (link.b == b || !b) { link = null; return; } links.push({from:link.b, to:b}); } else { for (var box of boxes) box.on_mouse_up(e); } link = null; }); $("#getlinks").click((e) => { var msg = ""; for (var l of links) { msg += `Box "${l.from.name}" свзяан с Box "${l.to.name}"
`; } $("#res").html(msg); }); new Box(10, 10, 50, 50); new Box(150, 150, 50, 50); function draw_boxes() { for (var box of boxes) { box.draw(); } } function draw_links() { for (var l of links) { var bc1 = l.from.center(), bc2 = l.to.center(); ctx.beginPath(); ctx.moveTo(bc1.x, bc1.y); ctx.lineTo(bc2.x, bc2.y); ctx.stroke(); } } function draw_link() { var bc = link.b.center(); ctx.beginPath(); ctx.moveTo(bc.x, bc.y); ctx.lineTo(link.t.x, link.t.y); ctx.stroke(); } function draw_all() { ctx.clearRect(0, 0, can.width, can.height); draw_links(); draw_boxes(); if (link) draw_link(); } draw_all(); html, body { margin: 0; padding: 0; }

This text is displayed if your browser does not support HTML5 Canvas.

MouseMove -- перемещение коробок.
Shift + Click -- добавить коробку.
Ctrl (на коробке) + MouseMove -- провести линию.