Pixels in YUV image - c++

I am using opencv to achieve object tracking. I read that YUV image is better option to use than RGB image. My problem is that I fail to understand about the YUV format although i spend much time read notes. Y is the brightness which i believe is calculated from the combination of R, G, B component.
My main problem is how can I access and manipulate the pixels in YUV image format. In RGB format its easy to access the component and therefore change it using simple operatin like
src.at<Vec3b>(j,i).val[0] = 0; for example
But this is not the case in YUV. I need help in accessing and changing the pixel values in YUV image. For example if pixel in RGB is red, then I want to only keep the corresponding pixel in YUV and the rest is removed. Please help me with this.

I would suggest operating on your image in HSV or LAB rather than RGB.
The raw image from the camera will be in YCbCr (sometimes called YUV, which I think is incorrect, but I may be wrong), and laid out in a way that resembles something like YUYV (repeating), so if you can convert directly from that to HSV, you will avoid additional copy and conversion operations which will save you some time. That may only matter to you if you're processing video or batches of images however.
Here's some C++ code for converting between YCbCr and RGB (one uses integer math, the other floating point):
Colour::bgr Colour::YCbCr::toBgrInt() const
{
int c0 = 22987;
int c1 = -11698;
int c2 = -5636;
int c3 = 29049;
int y = this->y;
int cb = this->cb - 128;
int cr = this->cr - 128;
int b = y + (((c3 * cb) + (1 << 13)) >> 14);
int g = y + (((c2 * cb + c1 * cr) + (1 << 13)) >> 14);
int r = y + (((c0 * cr) + (1 << 13)) >> 14);
if (r < 0)
r = 0;
else if (r > 255)
r = 255;
if (g < 0)
g = 0;
else if (g > 255)
g = 255;
if (b < 0)
b = 0;
else if (b > 255)
b = 255;
return Colour::bgr(b, g, r);
}
Colour::bgr Colour::YCbCr::toBgrFloat() const
{
float y = this->y;
float cb = this->cb;
float cr = this->cr;
int r = y + 1.40200 * (cr - 0x80);
int g = y - 0.34414 * (cb - 0x80) - 0.71414 * (cr - 0x80);
int b = y + 1.77200 * (cb - 0x80);
if (r < 0)
r = 0;
else if (r > 255)
r = 255;
if (g < 0)
g = 0;
else if (g > 255)
g = 255;
if (b < 0)
b = 0;
else if (b > 255)
b = 255;
return Colour::bgr(b, g, r);
}
And a conversion from BGR to HSV:
Colour::hsv Colour::bgr2hsv(bgr const& in)
{
Colour::hsv out;
int const hstep = 255 / 3; // Hue step size between red -> green -> blue
int min = in.r < in.g ? in.r : in.g;
min = min < in.b ? min : in.b;
int max = in.r > in.g ? in.r : in.g;
max = max > in.b ? max : in.b;
out.v = max; // v
int chroma = max - min;
if (max > 0)
{
out.s = 255 * chroma / max; // s
}
else
{
// r = g = b = 0 // s = 0, v is undefined
out.s = 0;
out.h = 0;
out.v = 0; // it's now undefined
return out;
}
if (chroma == 0)
{
out.h = 0;
return out;
}
const int chroma2 = chroma * 2;
int offset;
int diff;
if (in.r == max)
{
offset = 3 * hstep;
diff = in.g - in.b;
}
else if (in.g == max)
{
offset = hstep;
diff = in.b - in.r;
}
else
{
offset = 2 * hstep;
diff = in.r - in.g;
}
int h = offset + (diff * (hstep + 1)) / chroma2;
// Rotate such that red has hue 0
if (h >= 255)
h -= 255;
assert(h >= 0 && h < 256);
out.h = h;
return out;
Unfortunately I do not have code to do this in one step.
You can also use the built-in OpenCV functions for colour conversion.
cvtColor(img, img, CV_BGR2HSV);

Also the U and V components are calculated as linear combinations of RGB values. Then it means, that different intensities of red (R,0,0) are mapped to some (y*R + a,u*R + b, v*R + c), which again means that to detect "red" in YUV one can calculate if the distance of the pixel to that line determined by y,u,v,a,b,c (some of which are redundant) is close to zero. That's achievable with a single dot product. Then set the remaining pixels to the (0,128,128) in YUV space (I think that's R=0,G=0,B=0 in almost all varieties of YCrCb, YUV and such).

There are several YUV formats, but the common ones keep Y at the same resolution as the original image, but U and V are half size, and are saved as separate or interlaced planes/channels after the single channel Y image buffer.
This allows you to efficiently access Y as a 1-channel 8-bit greyscale image.

Access and manipulate pixels does not know the colorformat so the same code applies for color components Y U and V. If you need to access in RGB mode, best is probably calling cv::cvtColor for your region of interest first.

Related

How to downsample a not-power-of-2 texture in UnrealEngine?

I am rendering the Viewport with a resolution of something like 1920x1080 multiplied by a Oversampling value like 4. Now i need to downsample from the rendered Resolution 7680‬x4320 back to the 1920x1080.
Are there any functions in Unreal I could use for that ? Or any Library (windows only) which handle this nicely ?
Or what would be a propper way of writing this my own ?
We tried to implement a downsampling but it only works if SnapshotScale is 2, when its higher than 2 it doesn't seem to have an effect regarding image quality.
UTexture2D* AAVESnapShotManager::DownsampleTexture(UTexture2D* Texture)
{
UTexture2D* Result = UTexture2D::CreateTransient(RenderSettings.imageWidth, RenderSettings.imageHeight, PF_B8G8R8A8);
void* TextureDataVoid = Texture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_ONLY);
void* ResultDataVoid = Result->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
FColor* TextureData = (FColor*)TextureDataVoid;
FColor* ResultData = (FColor*)ResultDataVoid;
int32 WindowSize = RenderSettings.resolutionScale / 2;
for (int x = 0; x < Result->GetSizeX(); ++x)
{
for (int y = 0; y < Result->GetSizeY(); ++y)
{
const uint32 ResultIndex = y * Result->GetSizeX() + x;
uint32_t R = 0, G = 0, B = 0, A = 0;
int32 Samples = 0;
for (int32 dx = -WindowSize; dx < WindowSize; ++dx)
{
for (int32 dy = -WindowSize; dy < WindowSize; ++dy)
{
int32 PosX = (x * RenderSettings.resolutionScale + dx);
int32 PosY = (y * RenderSettings.resolutionScale + dy);
if (PosX < 0 || PosX >= Texture->GetSizeX() || PosY < 0 || PosY >= Texture->GetSizeY())
{
continue;
}
size_t TextureIndex = PosY * Texture->GetSizeX() + PosX;
FColor& Color = TextureData[TextureIndex];
R += Color.R;
G += Color.G;
B += Color.B;
A += Color.A;
++Samples;
}
}
ResultData[ResultIndex] = FColor(R / Samples, G / Samples, B / Samples, A / Samples);
}
}
Texture->PlatformData->Mips[0].BulkData.Unlock();
Result->PlatformData->Mips[0].BulkData.Unlock();
Result->UpdateResource();
return Result;
}
I expect a high quality oversampled Texture output, working with any positive int value in SnapshotScale.
I have a suggestion. It's not really direct, but it involves no writing of image filtering or importing of libraries.
Make an unlit Material with nodes TextureObject->TextureSample-> connect to Emissive.
Use the texture you start with in your function to populate the Texture Object on a Material Instance Dynamic of the material.
Use the "Draw Material to Render Target" function to draw the Material Instance Dynamic to a Render Target that is pre-set with your target resolution.

Different results between self-made bgr2hsv and opencv bgr2hsv

I implemented bgr2hsv function by accessing pixels with OpenCV, C++.
I just coded it with bgr2hsv algorithm on the Internet.
And I compared my bgr2hsv() to cvtColor() results.
Actually, result images has a little different colors even though the original image was same. I tried to see why different but I couldn't find it.
Could you see the source codes and result images?
Here's the code.
//self-made bgr2hsv
double b, g, r;
double bb, gg, rr;
double tmax, tmin;
double h = 0, s = 0, v = 0;
double del, delB, delG, delR;
Mat image = imread("lena.jpg", 1);
Mat clone1 = image.clone();
Mat img;
image.convertTo(img, CV_64F);
for (int y = 0; y < img.rows; y++)
{
for (int x = 0; x < img.cols; x++)
{
b = image.at<Vec3b>(y, x)[0];
g = image.at<Vec3b>(y, x)[1];
r = image.at<Vec3b>(y, x)[2];
bb = b / 255;
gg = g / 255;
rr = r / 255;
tmax = _max(bb, gg, rr);
tmin = _min(bb, gg, rr);
v = tmax;
del = tmax - tmin;
if (del == 0) {
h = 0;
s = 0;
}
else {
s = del / tmax;
delB = ((tmax - b) / 6 + del / 2) / del;
delG = ((tmax - g) / 6 + del / 2) / del;
delR = ((tmax - r) / 6 + del / 2) / del;
if (b == tmax) {
h = (2 / 3) + delG - delR;
}
if (g == tmax) {
h = (1 / 3) + delR - delB;
}
if (r == tmax) {
h = delB - delG;
}
if (h < 0) h += 1;
if (h > 1) h -= 1;
}
img.at<Vec3d>(y, x)[0] = h;
img.at<Vec3d>(y, x)[1] = s;
img.at<Vec3d>(y, x)[2] = v;
}
}
//bgr2hsv with cvtColor
cvtColor(image,clone1,CV_BGR2HSV);
imwrite("implemented_hsv.jpg",clone1);
imwrite("bgr2hsv.jpg", img);
//show images
imshow("bgr2hsv", img);
imshow("implemented_hsv",clone1);
waitKey(0);
And results are here.
enter image description here
I wouldn't suggest grabbing something from the internet and expecting it to give you the correct result unless you understand what's going on. Instead of using this, why not just use the formula from the OpenCV docs?
For an example of this particular conversion, see my answer here. It uses the exact formula OpenCV mentions in the docs linked above for BGR to HSV conversion. It's in Python and not C++, but Python is fairly easy to read anyways.

How to realize Digital fill light in Opencv

I want to realize the function of fill-light by use OpenCV, but There have some problem. Black part of pics is too dark, Photos become blurred, i don't know how to Optimization code。that my code:
V, value, 0~100, increase the amplitude of the brightness.
S,Scope, 0~255, dark is all less than S.
increase exposure to light dark photos increment, unchanged, so to see more details of the dark.
m_imgOriginal: original image ,type:Mat
m_imgNew: new image , clone from m_imgOriginal ,type:Mat
int OpenCVClass::AddExposure(int v, int s)
{
int new_r = v*m_mean_val.val[0] / 150;
int new_g = v*m_mean_val.val[1] / 150;
int new_b = v*m_mean_val.val[2] / 150;
for (int y = 0; y < m_imgOriginal.rows; y++)
{
auto ptr = m_imgOriginal.ptr<uchar>(y);
auto qtr = m_imgNew.ptr<uchar>(y);
for (int x = 0; x < m_imgOriginal.cols; x++)
{
int mean = (ptr[0] + ptr[1] + ptr[2]) / 3;
if (mean <= s)
{
int r = ptr[0] + new_r;
qtr[0] = r>255 ? 255 : r;
int g = ptr[1] + new_g;
qtr[1] = g>255 ? 255 : g;
int b = ptr[2] + new_b;
qtr[2] = b>255 ? 255 : b;
int newMean = (qtr[0] + qtr[1] + qtr[2]) / 3;
if (newMean > s)
{
int nr = ptr[0] + (s - mean) ;
int ng = ptr[1] + (s - mean) ;
int nb = ptr[2] + (s - mean) ;
qtr[0] = nr>255 ? 255 : nr;
qtr[1] = ng>255 ? 255 : ng;
qtr[2] = nb>255 ? 255 : nb;
}
}
else
{
qtr[0] = ptr[0];
qtr[1] = ptr[1];
qtr[2] = ptr[2];
}
ptr += 3;
qtr += 3;
}
RenderBuffer(m_imgNew, m_displayBuffer);
}
return 0;
}
Optimization before
Optimization after
First, I would suggest to calculate a luminance value for each pixel, when testing agains 's'. I mean calculate 'mean' a different way (see this link on how to calculate luminance):
http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
Second, you are dealing with an 8 bit per channel image, don't expect near-or-perfect dark pixels to have any extra detail when you make them "brighter", they will just become grey or whiter.
Third, when "adding" brightness, I suggest using the HSL representation of pixel color values and increasing the luminance. In pseudocode:
1) Convert pixel color from RGB to HSL.
2) Increase luminance (or 'lightness').
3) Convert back pixel color to RGB.

Linear color gradient not working

I'm currently attempting to create a color gradient class for my Mandelbrot Set explorer.
It reads the color constraints (RGBA8888 color and position between 0 and 1) from a text file and adds them to a vector, which is lateron used to determine colors at a certain position.
To compute a color, the algorithm searches the next constraint to either side from the given position, splits the color into the four single channels, and then, for each one, searches the lower of both and adds a portion of the difference equal to the ratio (x-lpos)/(upos-lpos) to the lower color. Afterwards, the channels are shifted and ORed together, and then returned as RGBA8888 unsigned integer. (See the code below.)
EDIT: I completely rewrote the gradient class, fixing some issues and making it more readable for the sake of debugging (It gets slow as hell, though, but -Os more or less takes care of that). However, It's still not as it's supposed to be.
class Gradient { //remade, Some irrelevant methods and de-/constructors removed
private:
map<double, unsigned int> constraints;
public:
unsigned int operator[](double value) {
//Forbid out-of-range values, return black
if (value < 0 || value > 1+1E-10) return 0xff;
//Find upper and lower constraint
auto upperC = constraints.lower_bound(value);
if (upperC == constraints.end()) upperC = constraints.begin();
auto lowerC = upperC == constraints.begin() ? prev(constraints.end(), 1) : prev(upperC, 1);
if (value == lowerC->first) return lowerC->second;
double lpos = lowerC->first;
double upos = upperC->first;
if (upos < lpos) upos += 1;
//lower color channels
unsigned char lred = (lowerC->second >> 24) & 0xff;
unsigned char lgreen = (lowerC->second >> 16) & 0xff;
unsigned char lblue = (lowerC->second >> 8) & 0xff;
unsigned char lalpha = lowerC->second & 0xff;
//upper color channels
unsigned char ured = (upperC->second >> 24) & 0xff;
unsigned char ugreen = (upperC->second >> 16) & 0xff;
unsigned char ublue = (upperC->second >> 8) & 0xff;
unsigned char ualpha = upperC->second & 0xff;
unsigned char red = 0, green = 0, blue = 0, alpha = 0xff;
//Compute each channel using
// lower color + dist(lower, x)/dist(lower, upper) * diff(lower color, upper color)
if (lred < ured)
red = lred + (value - lpos)/(upos - lpos) * (ured - lred);
else red = ured + (upos - value)/(upos - lpos) * (ured - lred);
if (lgreen < ugreen)
green = lgreen + (value - lpos)/(upos - lpos) * (ugreen - green);
else green = ugreen + (upos - value)/(upos - lpos) * (ugreen - lgreen);
if (lblue < ublue)
blue = lblue + (value - lpos)/(upos - lpos) * (ublue - lblue);
else blue = ublue + (upos - value)/(upos - lpos) * (ublue - lblue);
if (lalpha < ualpha)
alpha = lalpha + (value - lpos)/(upos - lpos) * (ualpha - lalpha);
else alpha = ualpha + (upos - value)/(upos - lpos) * (ualpha - lalpha);
//Merge channels together and return
return (red << 24) | (green << 16) | (blue << 8 ) | alpha;
}
void addConstraint(unsigned int color, double position) {
constraints[position] = color;
}
};
Usage in the update method:
image[r + rres*i] = grd[ratio];
//With image being a vector<unsigned int>, which is then used as data source for a `SDL_Texture` using `SDL_UpdateTexture`
It only works partially, though. When I only use a black/white gradient, the resulting image is as intended:
Gradient file:
2
0 000000ff
1 ffffffff
However, when I use a more colorful gradient (a linear version of the Ultra Fractal gradient, input file below), the image is far from the intended result the image still doesn't show the desired coloring:
Gradient file:
5
0 000764ff
.16 206bcbff
.42 edffffff
.6425 ffaa00ff
0.8575 000200ff
What am I doing wrong? I've rewritten the operator[] method multiple times, without anything changing.
Questions for clarification or general remarks on my code are welcome.
Your problem is due to an over-complicated interpolation function.
When linearly interpolating in the range a .. b using another factor r (with range 0 .. 1) to indicate the position in that range it's completely unnecessary to determine whether a or b is greater. Either way around you can just use:
result = a + r * (b - a)
If r == 0 this is trivially shown to be a, and if r == 1 the a - a cancels out leaving just b. Similarly if r == 0.5 then the result is (a + b) / 2. It simply doesn't matter if a > b or vice-versa.
The preferred formulation in your case, since it avoids the b - a subtraction that possibly hits range clamping limits is:
result = (1 - r) * a + r * b;
which given appropriate * and + operators on your new RGBA class gives this trivial implementation of your mid function (with no need for per-component operations since they're handled in those operators):
static RGBA mid(const RGBA& a, const RGBA& b, double r) {
return (1.0 - r) * a + r * b;
}
See https://gist.github.com/raybellis/4f69345d8e0c4e83411b, where I've also refactored your RGBA class to put the clamping operations in the constructor rather than within the individual operators.
After some extensive trial-and-error, I finally managed to get it working. (at this point many thanks to #Alnitak, who suggested using a separate RGBA color class.)
The major problem was that, when a color value of the upper constraint was lower than the one of the lower one, I still multiplied with the ratio (x-l)/(u-l), when instead I should have used its pendant, 1 - (x-l)/(u-l), to refer to the color of the upper constraint as the basis for the new one.
Here follows the implementation of the RGBA class and the fixed gradient class:
class RGBA {
private:
unsigned int red = 0, green = 0, blue = 0, alpha = 0;
public:
static RGBA mid(RGBA a, RGBA b, double r) {
RGBA color;
if (a.red < b.red) color.red = a.red + (b.red - a.red) * r;
else color.red = b.red + (a.red - b.red) * (1-r);
if (a.green < b.green) color.green = a.green + (b.green - a.green) * r;
else color.green = b.green + (a.green - b.green) * (1-r);
if (a.blue < b.blue) color.blue = a.blue + (b.blue - a.blue) * r;
else color.blue = b.blue + (a.blue - b.blue) * (1-r);
if (a.alpha < b.alpha) color.alpha = a.alpha + (b.alpha - a.alpha) * r;
else color.alpha = b.alpha + (a.alpha - b.alpha) * (1-r);
return color;
}
RGBA() {};
RGBA(unsigned char _red, unsigned char _green, unsigned char _blue, unsigned char _alpha) :
red(_red), green(_green), blue(_blue), alpha(_alpha) {};
RGBA(unsigned int _rgba) {
red = (_rgba >> 24) & 0xff;
green = (_rgba >> 16) & 0xff;
blue = (_rgba >> 8) & 0xff;
alpha = _rgba & 0xff;
};
operator unsigned int() {
return (red << 24) | (green << 16) | (blue << 8 ) | alpha;
}
RGBA operator+(const RGBA& o) const {
return RGBA((red + o.red) & 0xff, (green + o.green) & 0xff, (blue + o.blue) & 0xff, (alpha + o.alpha) & 0xff);
}
RGBA operator-(const RGBA& o) const {
return RGBA(min(red - o.red, 0u), min(green - o.green, 0u), min(blue - o.blue, 0u), min(alpha - o.alpha, 0u));
}
RGBA operator~() {
return RGBA(0xff - red, 0xff - green, 0xff - blue, 0xff - alpha);
}
RGBA operator*(double _f) {
return RGBA((unsigned int) min(red * _f, 0.) & 0xff, (unsigned int) min(green * _f, 0.) & 0xff,
(unsigned int) min(blue * _f, 0.) & 0xff, (unsigned int) min(alpha * _f, 0.) & 0xff);
}
};
class Gradient {
private:
map<double, RGBA> constraints;
public:
Gradient() {
constraints[0] = RGBA(0x007700ff);
constraints[1] = RGBA(0xffffffff);
}
~Gradient() {}
void addConstraint(RGBA color, double position) {
constraints[position] = color;
}
void reset() {
constraints.clear();
}
unsigned int operator[](double value) {
if (value < 0 || value > 1+1E-10) return 0xff;
auto upperC = constraints.lower_bound(value);
if (upperC == constraints.end()) upperC = constraints.begin();
auto lowerC = upperC == constraints.begin() ? prev(constraints.end(), 1) : prev(upperC, 1);
if (value == lowerC->first) return lowerC->second;
double lpos = lowerC->first;
double upos = upperC->first;
if (upos < lpos) upos += 1;
RGBA lower = lowerC->second;
RGBA upper = upperC->second;
RGBA color = RGBA::mid(lower, upper, (value-lpos)/(upos-lpos));
return color;
}
size_t size() {
return constraints.size();
}
};
This is the result:

Accessing certain pixel RGB value in openCV

I have searched internet and stackoverflow thoroughly, but I haven't found answer to my question:
How can I get/set (both) RGB value of certain (given by x,y coordinates) pixel in OpenCV? What's important-I'm writing in C++, the image is stored in cv::Mat variable. I know there is an IplImage() operator, but IplImage is not very comfortable in use-as far as I know it comes from C API.
Yes, I'm aware that there was already this Pixel access in OpenCV 2.2 thread, but it was only about black and white bitmaps.
EDIT:
Thank you very much for all your answers. I see there are many ways to get/set RGB value of pixel. I got one more idea from my close friend-thanks Benny! It's very simple and effective. I think it's a matter of taste which one you choose.
Mat image;
(...)
Point3_<uchar>* p = image.ptr<Point3_<uchar> >(y,x);
And then you can read/write RGB values with:
p->x //B
p->y //G
p->z //R
Try the following:
cv::Mat image = ...do some stuff...;
image.at<cv::Vec3b>(y,x); gives you the RGB (it might be ordered as BGR) vector of type cv::Vec3b
image.at<cv::Vec3b>(y,x)[0] = newval[0];
image.at<cv::Vec3b>(y,x)[1] = newval[1];
image.at<cv::Vec3b>(y,x)[2] = newval[2];
The low-level way would be to access the matrix data directly. In an RGB image (which I believe OpenCV typically stores as BGR), and assuming your cv::Mat variable is called frame, you could get the blue value at location (x, y) (from the top left) this way:
frame.data[frame.channels()*(frame.cols*y + x)];
Likewise, to get B, G, and R:
uchar b = frame.data[frame.channels()*(frame.cols*y + x) + 0];
uchar g = frame.data[frame.channels()*(frame.cols*y + x) + 1];
uchar r = frame.data[frame.channels()*(frame.cols*y + x) + 2];
Note that this code assumes the stride is equal to the width of the image.
A piece of code is easier for people who have such problem. I share my code and you can use it directly. Please note that OpenCV store pixels as BGR.
cv::Mat vImage_;
if(src_)
{
cv::Vec3f vec_;
for(int i = 0; i < vHeight_; i++)
for(int j = 0; j < vWidth_; j++)
{
vec_ = cv::Vec3f((*src_)[0]/255.0, (*src_)[1]/255.0, (*src_)[2]/255.0);//Please note that OpenCV store pixels as BGR.
vImage_.at<cv::Vec3f>(vHeight_-1-i, j) = vec_;
++src_;
}
}
if(! vImage_.data ) // Check for invalid input
printf("failed to read image by OpenCV.");
else
{
cv::namedWindow( windowName_, CV_WINDOW_AUTOSIZE);
cv::imshow( windowName_, vImage_); // Show the image.
}
The current version allows the cv::Mat::at function to handle 3 dimensions. So for a Mat object m, m.at<uchar>(0,0,0) should work.
uchar * value = img2.data; //Pointer to the first pixel data ,it's return array in all values
int r = 2;
for (size_t i = 0; i < img2.cols* (img2.rows * img2.channels()); i++)
{
if (r > 2) r = 0;
if (r == 0) value[i] = 0;
if (r == 1)value[i] = 0;
if (r == 2)value[i] = 255;
r++;
}
const double pi = boost::math::constants::pi<double>();
cv::Mat distance2ellipse(cv::Mat image, cv::RotatedRect ellipse){
float distance = 2.0f;
float angle = ellipse.angle;
cv::Point ellipse_center = ellipse.center;
float major_axis = ellipse.size.width/2;
float minor_axis = ellipse.size.height/2;
cv::Point pixel;
float a,b,c,d;
for(int x = 0; x < image.cols; x++)
{
for(int y = 0; y < image.rows; y++)
{
auto u = cos(angle*pi/180)*(x-ellipse_center.x) + sin(angle*pi/180)*(y-ellipse_center.y);
auto v = -sin(angle*pi/180)*(x-ellipse_center.x) + cos(angle*pi/180)*(y-ellipse_center.y);
distance = (u/major_axis)*(u/major_axis) + (v/minor_axis)*(v/minor_axis);
if(distance<=1)
{
image.at<cv::Vec3b>(y,x)[1] = 255;
}
}
}
return image;
}