How to get random value from assigned enum in c++? - c++

I want a random color from this enum:
enum Color {
red = 10,
black = 3,
pink = 6,
rainbow=99
};
Color my_randowm_color = ...
How can i do that?

There is no way to enumerate the values of an enum.
You can use a table:
std::vector<int> colors = {red, black, pink, rainbow};
and then pick a random element from it.
Picking a random element left as an exercise.

Note: This is a different approach based on my understanding of what the OP desires.
What you can do is generate a random number in a range of 0-3. As you have four colors. Then store your colors in an array. And use a function returning a random number as index of that array. In this manner You will get random colors among the ones you have.
eg.
random() {
// func definition
// return random number in range of array indices
}
array = ["red","black","pink","rainbow"];
array[random()];

You can create a array containing possible enums and then generate random number for array index starting from 0 to total possible enum values.
#include <iostream>
int main()
{
enum Color { red = 10, black = 3, pink = 6, rainbow=99 };
int max = 3;
int min = 0;
srand(static_cast <unsigned int> (time(0)));
int randNum = rand() % (max - min + 1) + min;
Color forRandomPurpose[] = { red, black, pink, rainbow };
Color my_random_color = forRandomPurpose[randNum];
std::cout << "Hello World!\n";
std::cout << my_random_color << std::endl;
}

Just for fun (-:
Color random_color() {
int r = rand() % 4;
return static_cast<Color>((r + 1) * 3 + (r >= 2) + (r >= 3) * 86);
}
Live demo: https://wandbox.org/permlink/j4YNMqWs41QJFeOB

Related

how can I change RGB values according to percentage

I want to change RGB values according to the percentage. means 0% should show Red , 50% should green and 100% will Blue color.I am working on fastled.I tried like this but didnt get the best result.can anyone suggest some good stuf??
int R,G,B;
int p = percentage;
if(p >= 0 and p <= 50){
R = abs(p - 100);
G = p*2;
}
if(p > 50 and p <= 100){
G = abs(p - 100);
B = p*2;
}
>! also tried
R = abs(p-100);
G = p/2;
B = p;
leds[0] = CRGB(R,G,B);
FastLED.show();
You need to convert percentage values to 8-bit binary values, i.e., convert values in the range [0,100] into values in the range [0,255] (which is [0x00,0xFF] in hex).
A simple scaling operation does this:
int r = pR * 255 / 100; // percentage red to hex
or equivalently:
int r = pR * 0xFF / 100; // percentage red to hex
The opposite conversion, from hex value to percentage, is just the reverse operation.
Note that since there are only 101 percentage values, you won't get all of the 256 possible 8-bit hex values when you do this conversion, but it should be close enough.
From your problem statement, you probably want something like this which generates RGB colors counter-clockwise around the sRGB color gamut from red to blue.
#include <array>
#include <string>
#include <cmath>
#include <iostream>
std::array<uint8_t, 3> getcolorpercent(double percent)
{
std::array<uint8_t, 3> rgb{};
int segment{static_cast<int>(percent/25)};
double percent_f = .01 * (percent - 25 * segment);
double col0{ 1 }, col1{ 1 };
if (segment % 2 == 0)
col1 = sqrt(4 * percent_f);
else
col0 = sqrt(1 - 4 * percent_f);
rgb[(segment / 2) % 3] = static_cast<uint8_t>(std::round(255*col0));
rgb[(1 + segment / 2) % 3] = static_cast<uint8_t>(std::round(255 * col1));
return rgb;
}
int main()
{
auto print = [](const std::array<uint8_t, 3> rgb, std::string descr) {
// note: 0+... is to convert uint8_t to int to precent interpreting as char
std::cout << descr << " red:" << 0+rgb[0] << " green:" << 0+rgb[1] << " blue:" << 0+rgb[2] << '\n';
};
std::array<uint8_t, 3> rgb_red = getcolorpercent(0);
std::array<uint8_t, 3> rgb_orange = getcolorpercent(15);
std::array<uint8_t, 3> rgb_yellow = getcolorpercent(25);
std::array<uint8_t, 3> rgb_cyan = getcolorpercent(75);
std::array<uint8_t, 3> rgb_violet = getcolorpercent(130);
print(rgb_red, "red=");
print(rgb_orange, "orange=");
print(rgb_yellow, "yellow=");
print(rgb_cyan, "cyan=");
print(rgb_violet, "violet=");
}
Output:
red= red:255 green:0 blue:0
orange= red:255 green:198 blue:0
yellow= red:255 green:255 blue:0
cyan= red:0 green:255 blue:255
violet= red:255 green:0 blue:228
This creates a (reversed) rainbow type from red to blue for 0% to 100%. Additionally, this has been expanded to allow percentages to exceed 100 which can be used to produces colors going from blue->violet->purple and back to red. Here's an image created from this going from percent 0 to 100:

C++ Program Hanging Indefinetely

I have written code to solve a programming problem.
To summarise the problem, I have three balls - red, green, and blue. I am given a number k. I have to systematically destroy each ball i.e., destroy one red, then move onto green, destroy one green, then move onto blue, destroy one blue, and then start over from red again.
In case there are zero balls, I should just move onto the next ball.
In the end, I have to return the colour of the k-th ball that is destroyed.
The constraints for this problem are:
r, g and b will each be between 1 and 1000000000000 (10^12), inclusive.
k will be between 1 and r+g+b, inclusive.
To solve this problem, I have written the following code:
std::string getColor(long r, long g, long b, long k)
{
long balls[] {r, g, b};
int index = 0;
long count = 0;
std::string lastDestroyed = "";
std::string colors[] {"RED", "GREEN", "BLUE"};
while (count != k)
{
if (balls[index] > 0)
{
balls[index]--;
lastDestroyed = colors[index];
count++;
index = (index + 1) % 3;
}
else
index = (index + 1) % 3;
}
return lastDestroyed;
}
My program produces the correct output for all the test cases for which I tested so far, except one, for which it hangs indefinitely. This is for the case in which
r = 1000000000000
g = 1
b = 1
k = 1000000000002
The correct output for this test case is "RED" but my program just hangs indefinitely. I would like to know what I did wrong to cause this. Any help will be deeply appreciated. Thank you.
==========
Here are a few more test cases and expected outputs in case my description of the problem isn't clear enough.
Input: r = 1, g = 1, b = 1, k = 3
Expected output: "BLUE"
Input: r = 3, g = 4, b = 5, k = 4
Expected output: "RED"
Input: r = 7, g = 7, b = 1, k = 7
Expected output: "GREEN"
The program is probably not hanging. Have a look at this, executed on my i9 system:
So if we extrapolate until we reach your input:
Your program will likely take (on my computer) around 10000s (2.8 hours) to run!
You are going to need to approach this issue differently, perhaps look into a mathematical or logical approach. For example, if you are destroying only reds in a row, won't you always destroy only reds?

Grid nearest neighbour BFS slow

Im trying to upsample my image. I fill the upsampled version with corresponding pixels in this way.
pseudocode:
upsampled.getPixel(((int)(x * factorX), (int)(y * factorY))) = old.getPixel(x, y)
as a result i end up with the bitmap that is not completely filled and I try to fill each not filled pixel with it's nearest filled neighbor.
I use this method for nn search and call it for each unfilled pixel. I do not flag unfilled pixel as filled after changing its value as it may create some weird patterns. The problem is that - it works but very slow. Execution time on my i7 9700k for 2500 x 3000 img scaled by factor x = 1,5 and y = 1,5 takes about 10 seconds.
template<typename T>
std::pair<int, int> cn::Utils::nearestNeighbour(const Bitmap <T> &bitmap, const std::pair<int, int> &point, int channel, const bool *filledArr) {
auto belongs = [](const cn::Bitmap<T> &bitmap, const std::pair<int, int> &point){
return point.first >= 0 && point.first < bitmap.w && point.second >= 0 && point.second < bitmap.h;
};
if(!(belongs(bitmap, point))){
throw std::out_of_range("This point does not belong to bitmap!");
}
auto hash = [](std::pair<int, int> const &pair){
std::size_t h1 = std::hash<int>()(pair.first);
std::size_t h2 = std::hash<int>()(pair.second);
return h1 ^ h2;
};
//from where, point
std::queue<std::pair<int, int>> queue;
queue.push(point);
std::unordered_set<std::pair<int, int>, decltype(hash)> visited(10, hash);
while (!queue.empty()){
auto p = queue.front();
queue.pop();
visited.insert(p);
if(belongs(bitmap, p)){
if(filledArr[bitmap.getDataIndex(p.first, p.second, channel)]){
return {p.first, p.second};
}
std::vector<std::pair<int,int>> neighbors(4);
neighbors[0] = {p.first - 1, p.second};
neighbors[1] = {p.first + 1, p.second};
neighbors[2] = {p.first, p.second - 1};
neighbors[3] = {p.first, p.second + 1};
for(auto n : neighbors) {
if (visited.find(n) == visited.end()) {
queue.push(n);
}
}
}
}
return std::pair<int, int>({-1, -1});
}
the bitmap.getDataIndex() works in O(1) time. Here's its implementation
template<typename T>
int cn::Bitmap<T>::getDataIndex(int col, int row, int depth) const{
if(col >= this->w or col < 0 or row >= this->h or row < 0 or depth >= this->d or depth < 0){
throw std::invalid_argument("cell does not belong to bitmap!");
}
return depth * w * h + row * w + col;
}
I have spent a while on debugging this but could not really find what makes it so slow.
Theoretically when scaling by factor x = 1,5, y = 1,5, the filled pixel should be no further than 2 pixels from unfilled one, so well implemented BFS wouldn't take long.
Also i use such encoding for bitmap, example for 3x3x3 image
* (each row and channel is in ascending order)
* {00, 01, 02}, | {09, 10, 11}, | {18, 19, 20},
c0 {03, 04, 05}, c1{12, 13, 14}, c2{21, 22, 23},
* {06, 07, 08}, | {15, 16, 17}, | {24, 25, 26},
the filled pixel should be no further than 2 pixels from unfilled one, so well implemented BFS wouldn't take long.
Sure, doing it once won’t take long. But you need to do this for almost every pixel in the output image, and doing lots of times something that doesn’t take long will still take long.
Instead of searching for a set pixel, use the information you have about the earlier computation to directly find the values you are looking for.
For example, in your output image, and set pixel, is at ((int)(x * factorX), (int)(y * factorY)), for integer x and y. So for a non-set pixel (a, b), you can find the nearest set pixel by ((int)(round(a/factorX)*factorX), (int)(round(b/factorY)*factorY)).
However, you are much better off directly upsampling the image in a simpler way: don’t loop over the input pixels, instead loop over the output pixels, and find the corresponding input pixel.

How to determine pixel intensity with respect to pixel range in x-axis?

I want to see the distribution of a color with respect to image width. That is, if a (black and white) image has width of 720 px, then I want to conclude that a specific range (e.g. pixels [500,720]) has more white color in compared to rest of the image. What I thought is, I need a slice of the image of 720x1 px, then I need to check the values and distribute them w.r.t. width of 720 px. But I don't know the way I can apply this in a suitable way?
edit: I use OpenCV 4.0.0 with C++.
Example Case: In the first image, it is obvious that right hand side pixels are white. I want to get estimate coordinates of this dense line or zone. The light pink zone is where I am interested in and the red borders are the range where I want to find it.
If you want to get minimum continious range of image columns which contain more white than the rest of the image, than you need first to calculate number of white pixels in each column. Lets assume we have an image 720x500 (500 pixels high and 720 pixels wide). Than you will get an array Arr of 720 elements that equal number of white pixels in each column (1x500) respectively.
const int Width = img.cols;
int* Arr = new int[Width];
for( int x = 0; x < Width; x++ ) {
Arr[x] = 0;
for( int y = 0; y < img.rows; y++ ) {
if ( img.at<cv::Vec3b>(y,x) == cv::Vec3b(255,255,255) ) {
Arr[x]++;
}
}
}
You need to find a minimum range [A;B] in this array that satisfies condition Sum(Arr[0 to A-1]) + Sum(Arr[B+1 to Width-1]) < Sum(Arr[A to B]).
// minimum range width is guaranteed to be less or equal to (Width/2 + 1)
int bestA = 0, minimumWidth = Width/2 + 1;
int total = RangeSum(Arr, 0, Width-1);
for (int i = 0; i < Width; i++) {
for (int j = i; j < Width && j < i + minimumWidth; j++) {
int rangeSum = RangeSum(Arr, i, j);
if (rangeSum > total - rangeSum) {
bestA = i;
minimumWidth = j - i + 1;
break;
}
}
}
std::cout << "Most white minimum range - [" << bestA << ";" << bestA + minimumWidth - 1 << "]\n";
You can optimize the code if you precalculate sums for all [0; i] ranges, i from 0 to Width - 1. Than you can calculate RangeSum(Arr, A, B) as PrecalculatedSums[B] - PrecalculatedSums[A] (in O(1) complexity).

SiftGPU and opencv::FundamentalMat

I'm trying to use cv::FindFundamentalMat but when I try to get the 4th argument (that should be :
Output array of N elements, every element of which is set to 0 for outliers and to 1 for the other points. The array is computed only in the RANSAC and LMedS methods. For other methods, it is set to all 1’s.
)
It only gives me 0's.
I'm using siftGPU to generate the keypoints (x,y) that are used in the function.
My code :
/*
... Use siftgpu
*/
std::vector<int(*)[2]> match_bufs; //Contain (x,y) from the 2 images that are paired
SiftGPU::SiftKeypoint & key1 = keys[match_bufs[i][0]];
SiftGPU::SiftKeypoint & key2 = keys[match_bufs[i][1]];
float x_l, y_l, x_r, y_r; //(x,y of left and right images)
x_l = key1.x; y_l = key1.y;
x_r = key2.x; y_r = key2.y;
vec1.push_back(x_l); vec1.push_back(y_l);
vec2.push_back(x_r); vec2.push_back(y_r);
std::vector<uchar> results;
int size = vec1.size();
results.resize(size);
std::vector<cv::Point2f> points1;
std::vector<cv::Point2f> points2;
for (int i = 0; i < size; i+=2) {
points1.push_back(cv::Point2f(vec1[i], vec1[i + 1]));
points2.push_back(cv::Point2f(vec2[i], vec2[i + 1]));
}
cv::Mat fund = cv::findFundamentalMat(points1, points2, CV_FM_RANSAC, 3, 0.99, results);
then,
std::cout << std::endl << fund << std::endl;
for (int j = 0; j < results.size(); ++j) {
std::cout << (int)results[j];
}
fund is :
0, -0.001, 0.6
0, 0, -0.3
-0.4, 0.2, 0
and results is composed with only 0's.
I'm maybe fooling myself because findFundamentalMat says :
Array of N points from the first image. The point coordinates should be floating-point (single or double precision).
Since i'm not native speaker english, there is maybe something that I'm missing... My (x,y) are like (350.0, 560.0) (that are floating points). But do I have to normalize them between [0,1] and that's what floating-point means?
Or do I am missing something else?
Thanks!
(EDIT : I tried to normalize my points (divide by height and width of respective images, but results are still 0's)
The answer is quite easy : I have to use the good format for the template and cast it well.
So :
((int)results.at<uchar>(i, 0) == 1)
works :)
If it can help someone.