Updating the question I am asking. I have successfully been able to convert from RGB to HSI and back again. I was given instruction by my professor to also increase the image intensity by adding ((1.0 - I) / 2.0) to I (intensity) before I output the image. When I do this it appear to be causing overflowing, hence all my checks for RGB, etc. If I subtract the above formula, it successfully darkens the image without the overflow issues. I can't seem to identify the cause of this overflow nor know how to correct it. I at first thought that it was related to values where R = G = B, but I have confirmed by outputting these variables and debugging that this isn't the case. What causes it is when the saturation, S, is equal to zero. When S = 0, I know that hue, H, is irrelevant. Any assistance would be greatly appreciated!
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#define M_PI (3.14159265358979323846)
using namespace cv;
int main(int argc, char * argv[])
{
if (argc <= 1)
{
std::cerr << "Not enough arguments." << std::endl;
return (1);
}
Mat img = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
std::cout << img.channels() << std::endl;
if (img.empty())
{
std::cerr << "Unable to open the image " << argv[1] << "." << std::endl;
return (1);
}
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
imshow("Original Image", img);
Mat hsi(img.rows, img.cols, img.type());
Mat newBGRimg = Mat::zeros(img.rows, img.cols, img.type());
double B, G, R, H, S, I, b, g, re;
int intB = 0, intG = 0, intR = 0;
for (int r = 0; r < img.rows; r++)
{
for (int c = 0; c < img.cols; c++)
{
b = img.at<Vec3b>(r, c)[0];
g = img.at<Vec3b>(r, c)[1];
re = img.at<Vec3b>(r, c)[2];
// Normalize colors
B = b / 255;
G = g / 255;
R = re / 255;
// BGR to HSI
double theta = acos((((R - G) + (R - B)) / 2) / (sqrt((pow((R - G), 2)) + ((R - B)*(G - B) + 0.0001))));
if (B <= G)
{
H = theta;
}
if (B > G)
{
H = (2 * M_PI) - theta;
}
if (H < 0)
H = 0;
if (H > 2 * M_PI)
H = 2 * M_PI;
double min = std::min({ B, G, R });
S = 1 - (3 * min) / (B + G + R); // / (B + G + R)
if (S < 0)
S = 0;
if (S > 1)
S = 1;
I = (B + G + R) / 3;
I = I + ((1.0 - I) / 2.0);
if (I < 0)
I = 0;
if (I > 1)
I = 1;
// HSI to BGR
if (H >= 0 && H < (2 * M_PI / 3))
{
B = I * (1 - S);
R = I * (1 + ((S * cos(H)) / (cos((M_PI / 3) - H))));
G = (3 * I) - (R + B);
B *= 255;
G *= 255;
R *= 255;
if (B > 255)
B = 255;
if (G > 255)
G = 255;
if (R > 255)
R = 255;
if (B < 0)
B = 0;
if (G < 0)
G = 0;
if (R < 0)
R = 0;
intB = (int)round(B);
intG = (int)round(G);
intR = (int)round(R);
//std::cout << intB << " " << intG << " " << intG << " " << r << " " << c << std::endl;
newBGRimg.at<Vec3b>(r, c)[0] = intB;
newBGRimg.at<Vec3b>(r, c)[1] = intG;
newBGRimg.at<Vec3b>(r, c)[2] = intR;
}
else if (H >= (2 * M_PI / 3) && H < (4 * M_PI / 3))
{
H = H - (2 * M_PI) / 3;
R = I * (1 - S);
G = I * (1 + ((S * cos(H)) / (cos((M_PI / 3) - H))));
B = (3 * I) - (R + G);
B *= 255;
G *= 255;
R *= 255;
if (B > 255)
B = 255;
if (G > 255)
G = 255;
if (R > 255)
R = 255;
if (B < 0)
B = 0;
if (G < 0)
G = 0;
if (R < 0)
R = 0;
intB = (int)round(B);
intG = (int)round(G);
intR = (int)round(R);
newBGRimg.at<Vec3b>(r, c)[0] = intB;
newBGRimg.at<Vec3b>(r, c)[1] = intG;
newBGRimg.at<Vec3b>(r, c)[2] = intR;
}
else if (H >= (4 * M_PI / 3))
{
H = H - (4 * M_PI) / 3;
G = I * (1 - S);
B = I * (1 + ((S * cos(H)) / (cos((M_PI / 3 - H)))));
R = (3 * I) - (G + B);
B *= 255;
G *= 255;
R *= 255;
if (B > 255)
B = 255;
if (G > 255)
G = 255;
if (R > 255)
R = 255;
if (B < 0)
B = 0;
if (G < 0)
G = 0;
if (R < 0)
R = 0;
intB = (int)round(B);
intG = (int)round(G);
intR = (int)round(R);
newBGRimg.at<Vec3b>(r, c)[0] = intB;
newBGRimg.at<Vec3b>(r, c)[1] = intG;
newBGRimg.at<Vec3b>(r, c)[2] = intR;
}
}
}
namedWindow("New RGB Image", CV_WINDOW_AUTOSIZE);
imshow("New RGB Image", newBGRimg);
imwrite("hsi-to-rgb.jpg", newBGRimg);
waitKey(0);
return 0;
}
In my original code I was trying to normalize the BGR values using for ex. B/B+G+R per DI 3rd edition supplemental material. . This should have been B/255 to normalize that to [0,1]. I believe the book was incorrect in suggesting this normalization method.
Related
I have the following code:
#!/usr/bin/env lua5.3
-- Code adapted from https://github.com/EmmanuelOga/columns/blob/master/utils/color.lua#L51
local function hslToRgb(h, s, l, a)
local r, g, b
h = (h / 255)
s = (s / 100)
l = (l / 100)
if s == 0 then
r, g, b = l, l, l -- achromatic
else
local function hue2rgb(p, q, t)
if t < 0 then t = t + 1 end
if t > 1 then t = t - 1 end
if t < 1/6 then return p + (q - p) * 6 * t end
if t < 1/2 then return q end
if t < 2/3 then return p + (q - p) * (2/3 - t) * 6 end
return p
end
local q
if l < 0.5 then q = l * (1 + s) else q = l + s - l * s end
local p = 2 * l - q
r = hue2rgb(p, q, h + 1/3)
g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h - 1/3)
end
if not a then a = 1 end
return r * 255, g * 255, b * 255, a * 255
end
local h,s,l,a
h,s,l,a = hslToRgb(220, 16.4, 21.6)
print(h,s,l,a)
-- expected output: 46 52 64 255
-- actual output: 64.11312 46.04688 60.92496 255
But, as stated at the end, the color values it outputs are completely wrong. The decimals are not an issue (as in, it's not an issue that it outputs them; their values are still wrong).
A hue value it's calculated in degrees, so the max isn't 255, but 360:
function hslToRgb(h, s, l)
h = h / 360
s = s / 100
l = l / 100
local r, g, b;
if s == 0 then
r, g, b = l, l, l; -- achromatic
else
local function hue2rgb(p, q, t)
if t < 0 then t = t + 1 end
if t > 1 then t = t - 1 end
if t < 1 / 6 then return p + (q - p) * 6 * t end
if t < 1 / 2 then return q end
if t < 2 / 3 then return p + (q - p) * (2 / 3 - t) * 6 end
return p;
end
local q = l < 0.5 and l * (1 + s) or l + s - l * s;
local p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
end
if not a then a = 1 end
return r * 255, g * 255, b * 255, a * 255
end
You can see this code working here.
I have been working on a more elegant solution to the HSV to RGB problem for a little bit now and this is what I've come up with.
local ceil = math.ceil
local abs = math.abs
local function clamp(v, min, max)
if v < min then return min end
if v > max then return max end
return v
end
local function HSV(h, s, v)
local vert = ceil(h / 120)
local r = abs(((h / 60) - 2 * vert))
local r, g, b = clamp(r, 1 - s, 1), clamp(2 - r, 1 - s, 1), (1 - s * v)
if vert == 1 then return r, g, b end
if vert == 2 then return b, r, g end
if vert == 3 then return g, b, r end
end
-- HSV to RGB
min = math.min
max = math.max
abs = math.abs
local function HSV2RGB (h, s, v)
local k1 = v*(1-s)
local k2 = v - k1
local r = min (max (3*abs (((h )/180)%2-1)-1, 0), 1)
local g = min (max (3*abs (((h -120)/180)%2-1)-1, 0), 1)
local b = min (max (3*abs (((h +120)/180)%2-1)-1, 0), 1)
return k1 + k2 * r, k1 + k2 * g, k1 + k2 * b
end
I need to plot a discrete signal that is defined by a piecewise function :
if n < 0 , x = (135/56) * (0.9)^n - (1/8)(0.1)^n - (2/7)(0.2)^n
if 0<=n< 4, x = (135/56) * (0.9)^n + (7/8)(0.1)^n + (5/7)(0.2)^n
if n>=4 , x = (135/56) * (0.9)^n + (7/8)(0.1)^n + (5/7)(0.2)^n + (0.1)^(-4) + (0.2)^(-4)
I have searched a lot in web and especially here and I came up with this code , that after many corrections it actually runned in spyder. But the result is definetely not the expected one. Can anyone help me?
import numpy as np
import matplotlib.pyplot as plt
xPoints = []
nPoints = []
q = (135 / 56)
z= -(1/8)
r = -(2/7)
m = 7/8
p = 5 /7
j = np.power(0.1, -3.5)
a = np.power(0.2, -3.5)
for n in range(-5,11):
if n<0 :
x = q *np.power(0.9, n) + z* np.power(0.1, n) + r* np.power(0.2, n)
elif (n>=0 and n<4):
x =q *np.power(0.9, n) + m* np.power(0.1, n) + p* np.power(0.2, n)
else:
x =q *np.power(0.9, n) + m* np.power(0.1, n) + p* np.power(0.2, n)+ j + a
xPoints.append(x)
nPoints.append(n)
plt.plot(nPoints, xPoints)
plt.plot.show()
In numpy stepwise functions can be created using where. One of numpy's most magical features is broadcasting, where a function can be called on a complete array of values at once.
Your example code creates the expected curve, but only adds a point at integer values. To create a smooth curve, np.linspace creates a long array of values (the code below uses 1000 little steps between -5 and 5). (Note that numpy needs the & operator for a logical and of two array expressions. In this particular case you could use n < 4 instead of (n >= 0) & (n < 4) as the case of n < 0 is taken care of earlier.)
import numpy as np
import matplotlib.pyplot as plt
q = (135 / 56)
z = -(1 / 8)
r = -(2 / 7)
m = 7 / 8
p = 5 / 7
j = np.power(0.1, -3.5)
a = np.power(0.2, -3.5)
n = np.linspace(-5, 5, 1000)
x = np.where(n < 0, q * np.power(0.9, n) + z * np.power(0.1, n) + r * np.power(0.2, n),
np.where((n >= 0) & (n < 4), q * np.power(0.9, n) + m * np.power(0.1, n) + p * np.power(0.2, n),
q * np.power(0.9, n) + m * np.power(0.1, n) + p * np.power(0.2, n) + j + a))
plt.plot(n, x)
plt.show()
If you only want the integer positions, you can use np.arange instead of np.linspace and then create a scatter plot (plt.scatter(n, x)) or maybe a stemplot:
import numpy as np
import matplotlib.pyplot as plt
q = (135 / 56)
z = -(1 / 8)
r = -(2 / 7)
m = 7 / 8
p = 5 / 7
j = np.power(0.1, -3.5)
a = np.power(0.2, -3.5)
n = np.arange(-5, 6)
x = np.where(n < 0, q * np.power(0.9, n) + z * np.power(0.1, n) + r * np.power(0.2, n),
np.where((n >= 0) & (n < 4), q * np.power(0.9, n) + m * np.power(0.1, n) + p * np.power(0.2, n),
q * np.power(0.9, n) + m * np.power(0.1, n) + p * np.power(0.2, n) + j + a))
plt.stem(n, x)
plt.show()
I tried check50, and I got some message for the command down below.
#include<cs50.h>
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
int main(int argc, string argv[])
{
string a = argv[1];
int s = strlen(a);
if(s == 0)
{
printf("No keyword entered\n");
return 1;
}
for(int k = 0; k < s; k++)
{
if(!isalpha(a[k]))
{
printf("keyword not alphabetical\n");
return 1;
}
}
string t = GetString();
int i = 0;
int x = 0;
int v = 65;
for(int n = strlen(t); i < n; i ++)
{
if(isalpha(t[i]))
{
if(isupper(t[i]))
{
if(isupper(t[i]))
{
if(islower(a[x]))
{
v = v + 32;
}
int p = a[x];
p = p -v;
int 1 =t[i];
1 = 1 - 65;
int b = (1+ p[s%x]%26;
b = b + 65;
char c = b;
printf("%c", c);
x = x+1;
}
if(islower(t[i]))
{
int p = a[x];
p = p - v;
int 1 = t[i];
1 = 1-97;
int b =(1 +p[s%x]%26;
b = b + 97;
char c = b;
printf("%c", c);
x = x + 1;
}
}
else
{
printf)"%c", t[i]);
}
}
printf('\n');
}
Error message:
:| encrypts "a" as "a" using "a" as keyword
:| encrypts "world, say hello!" as "xoqmd, rby gflkp!" using "baz" as keyword
:| encrypts "BaRFoo" as "CaQGon" using "BaZ" as keyword
:| encrypts "BARFOO" as "CAQGON" using "BAZ" as keyword
:| handles lack of argv[1]
:| handles argc > 2
:| rejects "Hax0r2" as keyword
How to fix it all?
I wrote a program which calculates the integral of the probability density function of the lognormal distribution.
I want it to be able to calculate the nth moments of the pdf too. But if I modify my code I get this error. It works properly before I add *(x^(M))
Function riemanint(n, a, b)
Dim h, i, x
h = (b - a) / n
x = a - h / 2
For i = 1 To n
x = x + h
s = s + f(x, ev, var, PI, M) * h
Next
riemanint = s
End Function
Function f(x, ev, var, PI, M)
PI = Application.WorksheetFunction.PI()
ev = Range("D2")
var = Range("E2")
M = Range("F2")
f = (((1 / (x * ((2 * PI) ^ 0.5) * var)) * Exp((-(Log(x) - ev) ^ 2) / (2 * var * var)))) * (x^(M))
End Function
Would it be possible to take a rgY color space:
r = R / (R + G + B)
g = G / (R + G + B)
Y = R * 0.299 + G * 0.587 + B * 0.114
(unnecessary) b = 1 - r - g
and convert it back to RGB? If so, how would it be done?
(No factorials are in this answer. The syntax is similar to Wolfram-Alpha plain text output standards, exception being spaces are placed before and after the != [not equals] sign and the use of 'if [conditional] then' statements.)
if r = 0 and 473 g+114 != 0 and Y != 0 then
R = 0 and G = (1000 g Y)/(473 g+114) and B = -(1000 (g-1) Y)/(473 g+114)
if Y = 0 and g = 1/473 (-185 r-114) and r != 0 then
G = -((185 r+114) R)/(473 r) and B = ((587-288 r) R)/(473 r) and R!=0
if Y = 0 and r = 0 and g = -114/473 then
R = 0 and B = -(587 G)/114 and G!=0
if 473 g+185 r+114 != 0 and r != 0 and r Y != 0
R = (1000 r Y)/(473 g+185 r+114) and G = (1000 g Y)/(473 g+185 r+114) and B = -(1000 Y (g+r-1))/(473 g+185 r+114)