I want to use the output of Matlab coder for image processing. I created an c++ output from Matlab coder, I would like to use this code for integrating it into some other application. The problem is we dont know exactly how the Matlab coder generates the image matrix into const unsigned char[...]. It would be great help if there is any possibility in checking the way it is created. So that we can create the image into unsigned char[..], the same way and convert it back to image.
This is the code generated by Matlab
* multiplyImage.c
*
* Code generation for function 'multiplyImage'
*
*/
/* Include files */
#include "rt_nonfinite.h"
#include "multiplyImage.h"
/* Function Declarations */
static double rt_roundd_snf(double u);
/* Function Definitions */
static double rt_roundd_snf(double u)
{
double y;
if (fabs(u) < 4.503599627370496E+15) {
if (u >= 0.5) {
y = floor(u + 0.5);
} else if (u > -0.5) {
y = u * 0.0;
} else {
y = ceil(u - 0.5);
}
} else {
y = u;
}
return y;
}
void multiplyImage(const unsigned char img[2115216], double parameter, unsigned
char imgout[2115216])
{
int i0;
double d0;
unsigned char u0;
/* implements a function that multiplies an image with a parameter */
for (i0 = 0; i0 < 2115216; i0++) {
d0 = rt_roundd_snf(parameter * (double)img[i0]);
if (d0 < 256.0) {
if (d0 >= 0.0) {
u0 = (unsigned char)d0;
} else {
u0 = 0;
}
} else if (d0 >= 256.0) {
u0 = MAX_uint8_T;
} else {
u0 = 0;
}
imgout[i0] = u0;
}
}
/* End of code generation (multiplyImage.c) */
I have an issue converting the unsigned char from the cpp file to multidimensional array, according to suggestion given as followed. But I have to represent the data in the format of c[] w[] h[], I am confused how to represent the red, green, blue information into c[] from following. I am confused is this the right way to represent it (as you can see this function is intended to get a const unsigned char[]) and create an output with three dimension c[] w[] h[] matrix. Any help would be great
double Marvin_To_UnsignedChar::Convert_To_Marvin_Image(const unsigned char input[])
{
int Initial_Color;
for (int Initial_Height = 0; Initial_Height < Height; ++Initial_Height)
{
for (int Initial_Width = 0; Initial_Width < Width; ++Initial_Width)
{
int red [Initial_Height * Width + Initial_Width] = input[Initial_Width * Height + Initial_Height];
int green[Initial_Height * Width + Initial_Width] = input[Height * Width + Initial_Width * Height + Initial_Height];
int blue [Initial_Height * Width + Initial_Width] = input[2 * Height * Width + Initial_Width * Height + Initial_Width * Height + 1];
int color((red[Initial_Height * Width + Initial_Width]) (green[Initial_Height * Width + Initial_Width]) (blue[Initial_Height * Width + Initial_Width]));
double Marvin_Matrix([color][Width][Height]);
return Marvin_Matrix([color][Width][Height]);
}
}
}
Related
We would like to perform bokeh blur on a image. I have tried to test some code below but could not get Circle of Confusion on bright point.
void bokeh(unsigned char *Input, unsigned char *Output, int Width, int Height, int Stride, int Radius)
{
int Channels = Stride / Width;
int rsq = fmax(1, sqrtf(Radius));
for (int y = 0; y < Height; y++)
{
unsigned char * LinePD = Output + y*Stride;
for (int x = 0; x < Width; x++)
{
unsigned int sum[3] = { 0 };
unsigned int weightsum = 0;
for (int ny = std::max(0, y - Radius); ny < std::min(y + Radius, Height); ny++)
{
const unsigned char * sampleLine = Input + ny*Stride;
for (int nx = std::max(0, x - Radius); nx < std::min(x + Radius, Width); nx++)
{
if (sqrtf(nx - x) + sqrtf(ny - y) < rsq)
{
const unsigned char * sample = sampleLine + nx*Channels;
const unsigned char&R = sample[0];
const unsigned char&G = sample[1];
const unsigned char&B = sample[2];
float weight = sqrtf((unsigned char)((21627 * R + 21627 * G + 21627 * B) >> 16));
for (int c = 0; c < Channels; c++)
{
sum[c] += weight*sample[c];
}
weightsum += weight;
}
}
}
for (int c = 0; c < Channels; c++)
{
LinePD[c] = ClampToByte(sum[c] / weightsum);
}
LinePD += Channels;
}
}
}
The source image is:
The result is:
while I expect effect is which like circular in pictures below
seems that I replace sqrtf(nx - x) + sqrtf(ny - y) < rsq
with
powf(nx - x, 2.0) + powf(ny - y, 2.0) < powf(Radius, 2)
and replace float weight = sqrtf((unsigned char)((21627 * R + 21627 * G + 21627 * B) >> 16));
with
float weight = (R + G + B)*1.0f/3.0f;
I could get bokeh blur effect, so how to set the weight to by brightness?
I'm starting with my c++ threads and don't understand some basic stuff. That's Mandelbrot example, it generates fractal image.
It's not my code, I just did some changes (here's original: https://rosettacode.org/wiki/Mandelbrot_set#PPM_non_interactive)
I have this function which generates matrix with colors to save to file:
vector<unsigned char *> drawMandelbrot()
{
/* screen ( integer) coordinate */
int iX, iY;
double Cx, Cy;
const double CxMin = -2.5;
const double CxMax = 1.5;
const double CyMin = -2.0;
const double CyMax = 2.0;
double PixelWidth = (CxMax - CxMin) / iXmax;
double PixelHeight = (CyMax - CyMin) / iYmax;
int Index = 0;
const int IterationMax = 200;
unsigned char color[3];
vector<unsigned char *> rows(MaxIndex);
double Zx, Zy;
double Zx2, Zy2;
int Iteration;
const double EscapeRadius = 2;
double ER2 = EscapeRadius * EscapeRadius;
for (iY = 0; iY < iYmax; iY++)
{
Cy = CyMin + iY * PixelHeight;
if (fabs(Cy) < PixelHeight / 2)
Cy = 0.0; /* Main antenna */
for (iX = 0; iX < iXmax; iX++)
{
Cx = CxMin + iX * PixelWidth;
/* initial value of orbit = critical point Z= 0 */
Zx = 0.0;
Zy = 0.0;
Zx2 = Zx * Zx;
Zy2 = Zy * Zy;
/* */
for (Iteration = 0; Iteration < IterationMax && ((Zx2 + Zy2) < ER2); Iteration++)
{
Zy = 2 * Zx * Zy + Cy;
Zx = Zx2 - Zy2 + Cx;
Zx2 = Zx * Zx;
Zy2 = Zy * Zy;
};
/* compute pixel color (24 bit = 3 bytes) */
if (Iteration == IterationMax)
{ /* interior of Mandelbrot set = black */
color[0] = 0;
color[1] = 0;
color[2] = 0;
}
else
{ /* exterior of Mandelbrot set = white */
color[0] = 255; /* Red*/
color[1] = 255; /* Green */
color[2] = 255; /* Blue */
};
rows[Index] = color;
Index++;
}
}
return rows;
}
Here is function to save it to file:
void saveToFile(vector<unsigned char *> matrix, char *filename)
{
char *comment = (char *)"# "; /* comment should start with # */
FILE *file;
file = fopen(filename, "wb"); /* b - binary mode */
fprintf(file, "P6\n %s\n %d\n %d\n %d\n", comment, iXmax, iYmax, MaxColorComponentValue);
for (int Index = 0; Index < MaxIndex; Index++)
{
fwrite(matrix[Index], 1, 3, file);
}
fclose(file);
}
Some global values and main loop:
const int iXmax = 1000;
const int iYmax = 1000;
const int MaxColorComponentValue = 255;
int const MaxIndex = (iXmax * iYmax) - 1;
int main()
{
clock_t start = clock();
vector<unsigned char *> image = drawMandelbrot();
clock_t stop = clock();
cout << (double(stop - start) / CLOCKS_PER_SEC) << " seconds\n";
char *filename = (char *)"new2.ppm";
saveToFile(image,filename);
return 0;
}
Problem is that generateMandelbrot() returns matrix like this:
image matrix
but it should be vector of elements looks like this which is actually color value:
color char
I know the problems is with color and image values types, but have any idea how it should look like.
Thanks!
This:
rows[Index] = color;
Is assigning the unsigned char * in your vector to the same array every time!
In other words it's like if I sell you ten cars and deliver the keys but they are all identical keys to the same car. Wouldn't you be upset?
Change your variables to use std::array:
using Color = std::array<unsigned char, 3>;
Color color;
vector<Color> rows(MaxIndex);
Now you have a vector of triples (Colors), instead of a vector of pointers that all point at the same triple.
I followed the code at this link read pixel value in bmp file to be able to read the RGB values of pixels and when I have the entire image as one color and read a random pixel's values they are correct. After this I tried to make it so the function would also try and find how many unique colors there were so I added a box with a different color to the image but the function still only finds one color. I'm wondering if maybe I'm somehow not looking at all the bytes contained in the BMP but I'm not sure how that would be as I'm new to trying this stuff.
To make sure the code wasn't finding different colored pixels but failing to add them to the list of unique pixels I tried printing output when a color is found that is different from the one that is always found but no output ever came from it.
struct Color {
int R = -1;
int G = -1;
int B = -1;
};
unsigned char* readBMP(char* filename) {
int i;
FILE* f = fopen(filename, "rb");
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f);
int width = *(int*)&info[18]; //the reason *(int*) is used here because there's an integer stored at 18 in the array that indicates how wide the BMP is
int height = *(int*)&info[22]; // same reasoning for *(int*)
int size = 3 * width * height;
unsigned char* data = new unsigned char[size];
fread(data, sizeof(unsigned char), size, f);
fclose(f);
// windows has BMP saved as BGR tuples and this switches it to RGB
for(i = 0; i < size; i += 3){
unsigned char tmp = data[i];
data[i] = data[i+2];
data[i+2] = tmp;
}
i = 0; // i is the x value of the pixel that is having its RGB values checked
int j = 0; // j is the y value of the pixel that is having its RGB values checked
unsigned char R = data[3 * (i * width + j)]; // value of R of the pixel at (i,j)
unsigned char G = data[3 * (i * width + j) + 1]; // value of G of the pixel at (i,j)
unsigned char B = data[3 * (i * width + j) + 2]; // value of B of the pixel at (i,j)
std::cout << "value of R is " << int(R);
std::cout << " value of G is " << int(G);
std::cout << " value of B is " << int(B);
Color num_colors[5];
int count;
int z;
int flag;
int iterator;
int sum;
for(count = 0; count < size; count += 1){
unsigned char R = data[3 * (i * width + j)];
unsigned char G = data[3 * (i * width + j) + 1];
unsigned char B = data[3 * (i * width + j) + 2];
sum = int(R) + int(G) + int(B);
if(sum != 301) {// 301 is the sum of the RGB values of the color that the program does manage to find
std::cout << sum;
}
flag = 0;
for(z = 0; z < 5; z += 1){
if(num_colors[z].R == R && num_colors[z].G == G && num_colors[z].B == B){
flag = 1;
}
}
if(flag == 1){
continue;
}
iterator = 0;
while(num_colors[iterator].R != -1){
iterator += 1;
}
num_colors[iterator].R = R;
num_colors[iterator].G = G;
num_colors[iterator].B = B;
}
int number = 0;
for(int r = 0; r < 5; r += 1){
std::cout << "\nValue of R here: " << num_colors[r].R;
if(num_colors[r].R != -1){
number += 1;
}
}
std::cout << "\nNumber of colors in image: " << number;
return data;
}
https://imgur.com/a/dXllIWL
This is the picture I'm using so there should be two colors found but the code only finds red pixels.
Your problem is that you are always checking the RGB values at (0,0)
i = 0; // i is the x value of the pixel that is having its RGB values checked
int j = 0; // j is the y value of the pixel that is having its RGB values checked
...
for(count = 0; count < size; count += 1){
unsigned char R = data[3 * (i * width + j)];
unsigned char G = data[3 * (i * width + j) + 1];
unsigned char B = data[3 * (i * width + j) + 2];
i and j defines the X and Y position of the pixel you are checking, but notice that you never change those in the loop. Your loop will keep doing the same thing over and over again. What you probably want is a double loop, going through all coordinates in your image:
for(int y=0; y<height; y++)
for(int x=0; x<width; x++){
unsigned char R = data[3 * (y * width + x) + 0];
unsigned char G = data[3 * (y * width + x) + 1];
unsigned char B = data[3 * (y * width + x) + 2];
I made a program in C++ which calculates the mandelbrot-set. Now I want to visualize it (save it in a picture). But when I try to save a 64k picture some problems come up. So what is the best way to save a picture of the pixels or at least to visual it?
Edit:
When I want to create a for Example 64K (61440 * 34560) image there will be the error "Access violation while writing at the position 0x0..." (originally on German and translated) and the program stops. This error appears with very high resolution. On lower resolutions the program works as it is supposed to.
#include <SFML\Graphics.hpp>
#include <stdlib.h>
#include <complex>
#include <cmath>
#include <thread>
//4K : 3840 * 2160
//8K : 7680 * 4320
//16K: 15360 * 8640
//32K: 30720 * 17280
//64K: 61440 * 34560
//128K:122880 * 69120
const unsigned long width = 61440; //should be dividable by ratioX & numberOfThreads!
const unsigned long height = 34560; //should be dividable by ratioY & numberOfThreads!
const unsigned int maxIterations = 500;
const unsigned int numberOfThreads = 6;
const int maxWidth = width / 3;
const int maxHeight = height / 2;
const int minWidth = -maxWidth * 2;
const int minHeight = -maxHeight;
const double ratioX = 3.0 / width;
const double ratioY = 2.0 / height;
sf::Image img = sf::Image();
int getsGreaterThan2(std::complex<double> z, int noIterations) {
double result;
std::complex<double> zTmp = z;
std::complex<double> c = z;
for (int i = 1; i != noIterations; i++) {
zTmp = std::pow(z, 2) + c;
if (zTmp == z) {
return 0;
}
z = std::pow(z, 2) + c;
result = std::sqrt(std::pow(z.real(), 2) + std::pow(z.imag(), 2));
if (result > 2) {
return i;
}
}
return 0;
}
void fillPixelArrayThreadFunc(int noThreads, int threadNr) { //threadNr ... starts from 0
double imgNumber;
double realNumber;
double tmp;
long startWidth = ((double)width) / noThreads * threadNr + minWidth;
long endWidth = startWidth + width / noThreads;
for (long x = startWidth; x < endWidth; x++) {
imgNumber = x * ratioX;
for (long y = minHeight; y < maxHeight; y++) {
realNumber = y * ratioY;
long xArray = x - minWidth;
long yArray = y - minHeight;
tmp = getsGreaterThan2(std::complex<double>(imgNumber, realNumber), maxIterations);
if (tmp == 0) {
img.setPixel(xArray, yArray, sf::Color(0, 0, 0, 255));
}
else {
img.setPixel(xArray, yArray, sf::Color(tmp / maxIterations * 128, tmp / maxIterations * 128, tmp / maxIterations * 255, 255));
}
}
}
}
int main() {
img.create(width, height, sf::Color::Black);
std::thread *threads = new std::thread[numberOfThreads];
for (int i = 0; i < numberOfThreads; i++) {
threads[i] = std::thread(std::bind(fillPixelArrayThreadFunc, numberOfThreads, i));
}
for (int i = 0; i < numberOfThreads; i++) {
threads[i].join();
}
img.saveToFile("filename.png");
return 1;
}
Your program fails during the call img.create(width, height, sf::Color::Black);.
When you step into the sf::Image::create function you end up here where the newPixels vector is created, this simply fails when width * height is too big as in your case:
////////////////////////////////////////////////////////////
void Image::create(unsigned int width, unsigned int height, const Color& color)
{
if (width && height)
{
// Create a new pixel buffer first for exception safety's sake
std::vector<Uint8> newPixels(width * height * 4);
^61440* ^34560 = 8'493'465'600 bytes !!
Conclusion: SFML cannot handle huge images.
The program runs but the curved line isn't being displayed .
Here is my code and note, I have 4 vertices in an array.
void GLWidget::drawControlPolygon(){
for (int i = 0; i < vertices.size()-1;i++){
drawEdge(vertices[i], vertices[i+1], RGBValue(0,0,0));
}
}
void GLWidget::drawDeCasteljau(float t) {
Point p;
int N_PTS = 4;
p.x = pow((1-t),3)*vertices[0].x+3* t * pow((1 -t), 2) * vertices[1].x + 3 * (1-t)*pow(t,2)*vertices[2].x+ pow (t, 3)*vertices[3].x;
p.y = pow((1-t),3)*vertices[0].y+3* t * pow((1 -t), 2) * vertices[1].y + 3 * (1-t)*pow(t,2)*vertices[2].y+ pow (t, 3)*vertices[3].y;
p.z = pow((1-t),3)*vertices[0].z+3* t * pow((1 -t), 2) * vertices[1].z + 3 * (1-t)*pow(t,2)*vertices[2].z+ pow (t, 3)*vertices[3].z;
int bezPoints[3][3] ;
for (float u = 0.0; u <= 1.0; u += t) {
for (int diag = N_PTS-2; diag >= 0; diag--) {
for (int i = 0; i <= diag; i++) {
int j = diag - i;
bezPoints[i][j] = (1.0-u)*bezPoints[i][j+1] + u*bezPoints[i+1][j];
}
}
// set the pixel for this parameter value
//Set pixel method for theImage object.
// void setPixel(Index row, Index col, Byte red, Byte green, Byte blue, Byte alpha=255);
// void setPixel(Index row, Index col, RGBValue colour, Byte alpha = 255);
theImage.setPixel(bezPoints[0], bezPoints[0][0], RGBValue());
}
}
void GLWidget::drawBezierCurve() {
}
for the full class here is the link to it...
https://www.dropbox.com/s/j6jw51uhz30m3tb/testApp.cc?dl=0
So far the output looks like this
Thanks!