I am using the Hough transform algorithm do determine lines.
Right now I am just taking the peak values from the matrix that are over a certain threshold, but I am getting a lot of duplicate lines that i want to merge into one.
This is the code for finding peaks:
int prevVal = INT_MIN;
const int NOISE = 110;
enum
{
Ascending,
Descending
} direction = Ascending;
std::vector<Peak>peaks;
for (int x = 0; x < m_matrixWidth - 1; x++) {
for (int y = 0; y < m_matrixHeight - 1; y++) {
double currentValue = m_matrix[x*m_matrixHeight + y];
if (prevVal < currentValue) {
direction = Ascending;
}
else if (prevVal > currentValue) {
if (direction != Descending) {
if (currentValue > NOISE) {
Peak peak(x, y, currentValue);
peaks.push_back(peak);
std::cout << "peak at index " << x*m_matrixHeight + y << ": " << prevVal << std::endl;
}
direction = Descending;
}
}
prevVal = currentValue;
}
}
return peaks;
This is how it looks:
If anyone knows, thanks.
Related
Suppose I have n circles of radius r. I want to place them randomly inside a rectangle of size AxA.
It is guaranteed that they fit. One can suppose that the sum of the area of all circles is about 60% of the area of the rectangle.
I can try it by doing a backtracking, trying to place, going back, etc., but there should be a better way to do it.
One possibility is to generate random points inside the rectangle without further constraints, and then move the points/centres iteratively (by little steps) such that avoiding overlapping. If two points are too near one from each other, each point can bring pressure to the other, to make it going away a little bit. The higher the pressure, the higher the move.
This process was implemented in C++. In the following simple code, to facilitate implementation, points and vectors are represented par std::complex type.
Note that I used srandand rand for test purpose. You may used better random algorithms, depending on your constraints.
According to the tests that I have performed, convergence seems guaranteed for a density of 60%. I also made some tests with a density of 70%: sometimes convergence, sometimes not.
Complexity is O(n^2 n_iter), where nis the number of circles and n_iterthe number of iterations.
n_iteris generally between 100 and 300, for a density of 60%. It could be decreased with relaxing the convergence criteria.
It could be seems high complexity, compared to other proposals in comments. In practice, for n = 15, the work is performed in less than 30ms on my PC. Huge time or fast enough, depending on the context. I have included a figure to illustrate the algorithm.
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <ctime>
#include <complex>
#include <cmath>
#include <tuple>
#include <ios>
#include <iomanip>
using dcomplex = std::complex<double>;
void print (const std::vector<dcomplex>& centers) {
std::cout << std::setprecision (9);
std::cout << "\ncenters:\n";
for (auto& z: centers) {
std::cout << real(z) << ", " << imag(z) << "\n";
}
}
std::tuple<bool, int, double> process (double A, double R, std::vector<dcomplex>& centers, int n_iter_max = 100) {
bool check = true;
int n = centers.size();
std::vector<dcomplex> moves (n, 0.0);
double acceleration = 1.0001; // to accelerate the convergence, if density not too large
// could be made dependent of the iteration index
double dmin;
auto limit = [&] (dcomplex& z) {
double zx = real(z);
double zi = imag(z);
if (zx < R) zx = R;
if (zx > A-R) zx = A-R;
if (zi < R) zi = R;
if (zi > A-R) zi = A-R;
return dcomplex(zx, zi);
};
int iter;
for (iter = 0; iter < n_iter_max; ++iter) {
for (int i = 0; i < n; ++i) moves[i] = 0.0;
dmin = A;
for (int i = 0; i < n; ++i) {
for (int j = i+1; j < n; ++j) {
auto vect = centers[i] - centers[j];
double dist = std::abs(vect);
if (dist < dmin) dmin = dist;
double x = std::max (0.0, 2*R*acceleration - dist) / 2.0;
double coef = x / (dist + R/10000);
moves[i] += coef * vect;
moves[j] -= coef * vect;
}
}
std::cout << "iteration " << iter << " dmin = " << dmin << "\n";
if (dmin/R >= 2.0 - 1.0e-6) break;
for (int i = 0; i < n; ++i) {
centers[i] += moves[i];
centers[i] = limit (centers[i]);
}
}
dmin = A;
for (int i = 0; i < n; ++i) {
for (int j = i+1; j < n; ++j) {
auto vect = centers[i] - centers[j];
double dist = std::abs(vect);
if (dist < dmin) dmin = dist;
}
}
std::cout << "Final: dmin/R = " << dmin/R << "\n";
check = dmin/R >= 2.0 - 1.0e-6;
return {check, iter, dmin};
}
int main() {
int n = 15; // number of circles
double R = 1.0; // ray of each circle
double density = 0.6; // area of all circles over total area A*A
double A; // side of the square
int n_iter = 1000;
A = sqrt (n*M_PI*R*R/density);
std::cout << "number of circles = " << n << "\n";
std::cout << "density = " << density << "\n";
std::cout << "A = " << A << std::endl;
std::vector<dcomplex> centers (n);
std::srand(std::time(0));
for (int i = 0; i < n; ++i) {
double x = R + (A - 2*R) * (double) std::rand()/RAND_MAX;
double y = R + (A - 2*R) * (double) std::rand()/RAND_MAX;
centers[i] = {x, y};
}
auto [check, n_iter_eff, dmin] = process (A, R, centers, n_iter);
std::cout << "check = " << check << "\n";
std::cout << "Relative min distance = " << std::setprecision (9) << dmin/R << "\n";
std::cout << "nb iterations = " << n_iter_eff << "\n";
print (centers);
return 0;
}
I have a point cloud data with wide range in all 3 dimensions. I have filtered it using pcl::ConditionalRemoval::filter() in range -20 >= x >= 20, -20 >= y >= 20 and -2 >= z >= 2.
Now I want to have min and max values in each dimension, so I searched online for nay PCL function. I got pcl::getMinMax3D. I used it and to verify I also manually searched in the cloud data. The code is as below:
float xmin = 10000, xmax=-10000;
cout << "Manual Search Result:"<<endl;
for(unsigned int i = 0; i < filtered_data->size(); i++)
{
if(filtered_data->at(i)._PointXYZ::x > xmax)
xmax = filtered_data->at(i)._PointXYZ::x;
if(filtered_data->at(i)._PointXYZ::x < xmin)
xmin = filtered_data->at(i)._PointXYZ::x;
}
cout << "Xmin: " << xmin << "\t\tXmax: " << xmax << endl;
float ymin = 10000, ymax=-10000;
for(unsigned int i = 0; i < filtered_data->size(); i++)
{
if(filtered_data->at(i)._PointXYZ::y > ymax)
ymax = filtered_data->at(i)._PointXYZ::y;
if(filtered_data->at(i)._PointXYZ::y < ymin)
ymin = filtered_data->at(i)._PointXYZ::y;
}
cout << "Ymin: " << ymin << "\t\tYmax: " << ymax << endl;
float zmin = 10000, zmax=-10000;
for(unsigned int i = 0; i < filtered_data->size(); i++)
{
if(filtered_data->at(i)._PointXYZ::z > zmax)
zmax = filtered_data->at(i)._PointXYZ::z;
if(filtered_data->at(i)._PointXYZ::z < zmin)
zmin = filtered_data->at(i)._PointXYZ::z;
}
cout << "Zmin: " << zmin << "\t\tZmax: " << zmax << endl;
pcl::PointXYZ minPt, maxPt;
pcl::getMinMax3D (*filtered_data, minPt, maxPt);
cout << "getMinMax3D Search Result:"<<endl;
std::cout << "Min x: " << minPt.x << "\t\tMax x: " << maxPt.x << std::endl;
std::cout << "Min y: " << minPt.y << "\t\tMax y: " << maxPt.y << std::endl;
std::cout << "Min z: " << minPt.z << "\t\tMax z: " << maxPt.z << std::endl;
The output I m getting is:
Manual Search Result:
Xmin: -19.992 Xmax: 19.915
Ymin: -19.75 Ymax: 19.982
Zmin: -1.999 Zmax: 1.059
getMinMax3D Search Result:
Min x: -3.895 Max x: 3.967
Min y: -4.238 Max y: 4.291
Min z: -1.887 Max z: 0
Is my understanding wrong about the usage of getMinMax3D()?
If the input cloud has NAN point, make sure you set cloud.is_dense as false, otherwise the function pcl::getMinMax3D would not check for NaN.
Here is original implementation from https://pointclouds.org/documentation/common_2include_2pcl_2common_2impl_2common_8hpp_source.html
template <typename PointT> inline void
pcl::getPointsInBox (const pcl::PointCloud<PointT> &cloud,
Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt,
Indices &indices)
{
indices.resize (cloud.size ());
int l = 0;
// If the data is dense, we don't need to check for NaN
if (cloud.is_dense)
{
for (std::size_t i = 0; i < cloud.size (); ++i)
{
// Check if the point is inside bounds
if (cloud[i].x < min_pt[0] || cloud[i].y < min_pt[1] || cloud[i].z < min_pt[2])
continue;
if (cloud[i].x > max_pt[0] || cloud[i].y > max_pt[1] || cloud[i].z > max_pt[2])
continue;
indices[l++] = int (i);
}
}
// NaN or Inf values could exist => check for them
else
{
for (std::size_t i = 0; i < cloud.size (); ++i)
{
// Check if the point is invalid
if (!std::isfinite (cloud[i].x) ||
!std::isfinite (cloud[i].y) ||
!std::isfinite (cloud[i].z))
continue;
// Check if the point is inside bounds
if (cloud[i].x < min_pt[0] || cloud[i].y < min_pt[1] || cloud[i].z < min_pt[2])
continue;
if (cloud[i].x > max_pt[0] || cloud[i].y > max_pt[1] || cloud[i].z > max_pt[2])
continue;
indices[l++] = int (i);
}
}
indices.resize (l);
}
Given a set of positive integers and value X, find a subset S whose sum is >= X, such that sum(S) is the lowest of all sums of such existing subsets.
Can it be done in polynomial time? What would be the solution?
Checking all subsets is 2^n.
Backtracking is a possibility for this problem.
It allows examining all the possibilities recursively, without the need of a large amount of memory.
It stops as soon as an optimal solution is found: sum = X, up to a given tolerance (for example 10^-10 in the programme below)
It allows to implement a simple procedure of premature abandon:
at a given time, if sum + the sum of all remaining elements is higher than X, then we can give up examining the current path, without examining the remaining elements. This procedure is optimized by sorting the input data in decreasing order
Here is a code, in C++. The code being quite basic, it should be easy to migrate it to another language.
This programme tests the algorithm with random (uniform) elements, and display the number of iterations.
The complexity (i.e. the number of iterations) is really varying with the random elements (of course), but also greatly depends of the tolerance that we accept. With a tolerance of 10^-10 and a size of n=100, the complexity generally stays quite acceptable. It is no longer the case with a smaller tolerance.
With n = 100 and five runs, I obtained for the number of iterations: 6102, 3672, 8479, 2235, 12926. However, it is clear that there is no warranty to have good performances in all cases. For n = 100, the number of candidates (subsets) is huge.
// Find min sum greater than a given number X
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <tuple>
#include <cstdlib>
#include <cmath>
#include <ctime>
std::tuple<double, std::vector<double>> min_sum_greater(std::vector<double> &a, double X) {
int n = a.size();
std::vector<bool> parti (n, false); // current partition studies
std::vector<bool> parti_opt (n, false); // optimal partition
std::vector<double> sum_back (n, 0); // sum of remaining elements
//std::cout << "n = " << n << " \tX = " << X << "\n";
std::sort(a.begin(), a.end(), std::greater<double>());
sum_back[n-1] = a[n-1];
for (int i = n-2; i >= 0; --i) {
sum_back[i] = sum_back[i+1] + a[i];
}
double sum = 0.0; // current sum
int i = 0; // index of the element being examined
double best_sum = sum_back[0] + 1.0;
bool up_down = true;
double eps = 1.0e-10; // error tolerance
long long cpt = 0; // to check the number of iterations
while (true) { // UP
//std::cout << "Start of while loop: i = " << i << "\n";
cpt++;
if (up_down) {
bool abandon = (sum + sum_back[i] < X - eps) || (sum > best_sum);
if (abandon) { //premature abandon
parti[i] = false;
up_down = false;
i--;
continue;
}
parti[i] = true;
sum += a[i];
//std::cout << "UP, i = " << i << " \tsum = " << sum << "\n";
if (fabs(sum - X) < eps) {
best_sum = sum;
parti_opt = parti;
break;
}
if (sum >= X) {
if (sum < best_sum) {
best_sum = sum;
parti_opt = parti;
//std::cout << "i = " << i << " \tbest sum = " << best_sum << "\n";
}
parti[i] = false;
sum -= a[i];
}
if (i == (n-1)) { // leaf
up_down = false;
i--;
continue;
}
i++;
} else { // DOWN
if (i < 0) break;
if (parti[i]) {
sum -= a[i];
parti[i] = false;
i++;
up_down = true;
} else {
i--;
up_down = false;
}
}
}
std::vector<double> answer;
for (int i = 0; i < n; ++i) {
if (parti_opt[i]) answer.push_back (a[i]);
}
std::cout << "number of iterations = " << cpt << " for n = " << n << "\n";
return std::make_tuple (best_sum, answer);
}
int main () {
//std::vector<double> a = {5, 6, 2, 10, 2, 3, 4, 13, 17, 38, 42};
double X = 33.5;
srand (time(NULL));
int n = 100;
double vmax = 100;
X = vmax * n / 4;
std::vector<double> a (n);
for (int i = 0; i < n; ++i) {
a[i] = vmax * double(rand())/RAND_MAX;
}
double sum;
std::vector<double> y;
std::tie (sum, y) = min_sum_greater (a, X);
std::cout << std::setprecision(15) << "sum = " << sum << "\n";
if (n < 20) {
std::cout << "set: ";
for (auto val: y) {
std::cout << val << " ";
}
std::cout << "\n";
}
}
I have an array which is constituted of only 0s and 1s. Task is to find index of a 0, replacing which with a 1 results in the longest possible sequence of ones for the given array.
Solution has to work within O(n) time and O(1) space.
Eg:
Array - 011101101001
Answer - 4 ( that produces 011111101001)
My Approach gives me a result better than O(n2) but times out on long string inputs.
int findIndex(int[] a){
int maxlength = 0; int maxIndex= -1;
int n=a.length;
int i=0;
while(true){
if( a[i] == 0 ){
int leftLenght=0;
int j=i-1;
//finding count of 1s to left of this zero
while(j>=0){
if(a[j]!=1){
break;
}
leftLenght++;
j--;
}
int rightLenght=0;
j=i+1;
// finding count of 1s to right of this zero
while(j<n){
if(a[j]!=1){
break;
}
rightLenght++;
j++;
}
if(maxlength < leftLenght+rightLenght + 1){
maxlength = leftLenght+rightLenght + 1;
maxIndex = i;
}
}
if(i == n-1){
break;
}
i++;
}
return maxIndex;
}
The approach is simple, you just need to maintain two numbers while iterating through the array, the current count of the continuous block of one, and the last continuous block of one, which separated by zero.
Note: this solution assumes that there will be at least one zero in the array, otherwise, it will return -1
int cal(int[]data){
int last = 0;
int cur = 0;
int max = 0;
int start = -1;
int index = -1;
for(int i = 0; i < data.length; i++){
if(data[i] == 0){
if(max < 1 + last + cur){
max = 1 + last + cur;
if(start != -1){
index = start;
}else{
index = i;
}
}
last = cur;
start = i;
cur = 0;
}else{
cur++;
}
}
if(cur != 0 && start != -1){
if(max < 1 + last + cur){
return start;
}
}
return index;
}
O(n) time, O(1) space
Live demo: https://ideone.com/1hjS25
I believe the problem can we solved by just maintaining a variable which stores the last trails of 1's that we saw before reaching a '0'.
int last_trail = 0;
int cur_trail = 0;
int last_seen = -1;
int ans = 0, maxVal = 0;
for(int i = 0; i < a.size(); i++) {
if(a[i] == '0') {
if(cur_trail + last_trail + 1 > maxVal) {
maxVal = cur_trail + last_trail + 1;
ans = last_seen;
}
last_trail = cur_trail;
cur_trail = 0;
last_seen = i;
} else {
cur_trail++;
}
}
if(cur_trail + last_trail + 1 > maxVal && last_seen > -1) {
maxVal = cur_trail + last_trail + 1;
ans = last_seen;
}
This can be solved by a technique that is known as two pointers. Most two-pointers use O(1) space and O(n) time.
Code : https://www.ideone.com/N8bznU
#include <iostream>
#include <string>
using namespace std;
int findOptimal(string &s) {
s += '0'; // add a sentinel 0
int best_zero = -1;
int prev_zero = -1;
int zeros_in_interval = 0;
int start = 0;
int best_answer = -1;
for(int i = 0; i < (int)s.length(); ++i) {
if(s[i] == '1') continue;
else if(s[i] == '0' and zeros_in_interval == 0) {
zeros_in_interval++;
prev_zero = i;
}
else if(s[i] == '0' and zeros_in_interval == 1) {
int curr_answer = i - start; // [start, i) only contains one 0
cout << "tried this : [" << s.substr(start, i - start) << "]\n";
if(curr_answer > best_answer) {
best_answer = curr_answer;
best_zero = prev_zero;
}
start = prev_zero + 1;
prev_zero = i;
}
}
cout << "Answer = " << best_zero << endl;
return best_zero;
}
int main() {
string input = "011101101001";
findOptimal(input);
return 0;
}
This is an implementation in C++. The output looks like this:
tried this : [0111]
tried this : [111011]
tried this : [1101]
tried this : [10]
tried this : [01]
Answer = 4
I have two strings, say str1 and str2. I need to convert the first one to the second one while making the least number of edits. This is what is called as Edit Distance. Suppose we need to convert Sunday to Saturday. The first letter is the same, and the last three are the same as well, so it boils down to converting un to atur. This can be done in 3 steps - Replace 'n' with 'r', insert 't', insert 'a'. That gives the edit distance as 3. Following is the program to find out the edit distance -
// A Dynamic Programming based C++ program to find minimum
// number operations to convert str1 to str2
#include<bits/stdc++.h>
using namespace std;
// Utility function to find minimum of three numbers
int min(int x, int y, int z)
{
return min(min(x, y), z);
}
int editDistDP(string str1, string str2, int m, int n)
{
// Create a table to store results of subproblems
int dp[m+1][n+1];
// Fill d[][] in bottom up manner
for (int i=0; i<=m; i++)
{
for (int j=0; j<=n; j++)
{
// If first string is empty, only option is to
// isnert all characters of second string
if (i==0)
dp[i][j] = j; // Min. operations = j
// If second string is empty, only option is to
// remove all characters of second string
else if (j==0)
dp[i][j] = i; // Min. operations = i
// If last characters are same, ignore last char
// and recur for remaining string
else if (str1[i-1] == str2[j-1])
dp[i][j] = dp[i-1][j-1];
// If last character are different, consider all
// possibilities and find minimum
else
dp[i][j] = 1 + min(dp[i][j-1], // Insert
dp[i-1][j], // Remove
dp[i-1][j-1]); // Replace
}
}
return dp[m][n];
}
// Driver program
int main()
{
// your code goes here
string str1 = "sunday";
string str2 = "saturday";
cout << editDistDP(str1, str2, str1.length(), str2.length());
return 0;
}
While this returns the correct result, I also need to output the exact steps of conversion, i.e. something like
Sunday -> Surday -> Sturday -> Saturday.
How do I do the second step?
Once you have created your dp table, you can work your way back rom (m, n) to (0, 0) in the same way as you created the table.
Here's a solution that prints the modifications, but you could also return a vector of modifications.
int editDistDP(string str1, string str2)
{
int m = str1.length();
int n = str2.length();
int dp[m + 1][n + 1];
int i, j;
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0) {
dp[i][j] = j;
} else if (j == 0) {
dp[i][j] = i;
} else if (str1[i-1] == str2[j-1]) {
dp[i][j] = dp[i-1][j-1];
} else {
dp[i][j] = 1 + min3(dp[i][j - 1],
dp[i - 1][j],
dp[i - 1][j - 1]);
}
}
}
i = m; j = n;
while (i && j) {
if (i == 0) {
cout << "insert " << str2[j - 1] << endl;
j--;
} else if (j == 0) {
cout << "remove " << str1[i - 1] << endl;
i--;
} else if (str1[i - 1] == str2[j - 1]) {
i--; j--;
} else {
int k = imin3(dp[i][j - 1],
dp[i - 1][j],
dp[i - 1][j - 1]);
if (k == 2) {
cout << "replace " << str1[i - 1]
<< " with " << str2[j - 1] << endl;
i--; j--;
} else if (k == 1) {
cout << "remove " << str1[i - 1] << endl;
i--;
} else {
cout << "insert " << str2[j - 1] << endl;
j--;
}
}
}
return dp[m][n];
}
Here, imin3 is a function that returns the index 0, 1 or 2 of the minimum element in the list.