Receive values from dynamic array - c++

I recently asked question about how to work with element Edit1 dynamically, now I want to ask something about values, which I received from dynamical arrays. First I try to divide image into sectors:
const n=20;
unsigned short i, j, line_length, w = Image1->Width, h = Image1->Height, l = Left + Image1->Left, t = Top + Image1->Top;
unsigned short border = (Width-ClientWidth)/2, topborder = Height-ClientHeight-border;
Image1->Canvas->Pen->Color = clRed;
for (i = 0; i <= n; i++)
{
Image1->Canvas->MoveTo(0, 0);
line_length = w * tan(M_PI/2*i/n);
if (line_length <= h)
Image1->Canvas->LineTo(w, line_length);
else
{
line_length = h * tan(M_PI/2*(1-1.*i/n));
Image1->Canvas->LineTo(line_length, h);
}
}
Then I use regions to count black dots in each sector and I want to add values to element Memo:
HRGN region[n];
TPoint points[3];
points[0] = Point(l + border, t + topborder);
for (i = 0; i < n; i++)
{
for (j = 0; j <= 1; j++)
{
line_length = w * tan(M_PI/2*(i+j)/n);
if (line_length <= h)
points[j+1] = Point(l + border + w, t + topborder + line_length);
else
{
line_length = h * tan(M_PI/2*(1-1.*(i+j)/n));
points[j+1] = Point(l + border + line_length, t + topborder + h);
}
}
region[i] = CreatePolygonRgn(points, 3, ALTERNATE); // or WINDING ?? as u want
}
Byte k;
unsigned __int64 point_count[n] = {0}, points_count = 0;
for(j = 0; j < h; j++)
for (i = 0; i < w; i++)
if (Image1->Canvas->Pixels[i][j] == clBlack)
{
points_count++;
for (k = 0; k < n; k++)
if (PtInRegion(region[k], l + border + i, t + topborder + j))
point_count[k]++;
}
unsigned __int64 sum = 0;
for (i = 0; i < n; i++)
{
sum += point_count[i];
Memo1->Lines->Add(point_count[i]);
}
As i received an advice from one man, in order to allocate an array using a TEdit to specify the array's count I should use, for example DynamicArray:
#include <sysdyn.h>
DynamicArray<HRGN> region;
...
int n = Edit1-> Text.ToInt();
region.Length = n;
I have made the same changes to point_count array:
Byte k;
DynamicArray<unsigned __int64> point_count;
point_count.Length = n;
unsigned __int64 /*point_count[n] = {0},*/ points_count = 0;
...
The problem is that I received different values if I do it dynamically or statically(n=20).
Statically:
Dynamically:

The problem is that I received different values if I do it dynamically or statically(n=20)
There is no difference whatsoever in accessing elements of a static array vs a dynamic array. Your problem has to be elsewhere.
For instance, your static code is initializing all of the array elements to 0, but your dynamic code is not doing that, so they will have random values before your loop then increments them.
Try this:
DynamicArray<unsigned __int64> point_count;
point_count.Length = n;
for(int i = 0; i < n; ++i) {
point_count[i] = 0;
}
...
Alternatively:
DynamicArray<unsigned __int64> point_count;
point_count.Length = n;
ZeroMemory(&point_count[0], sizeof(unsigned __int64) * n);
...
Also, using the Image1->Canvas->Pixels[][] property is very slow. Consider using the Image1->Picture->Bitmap->ScanLine[] property instead for faster access to the raw pixels.

Related

stack overflow error but cant allocate on the heap

I am trying to multithread a raytracer, and am trying to write a function to pass into the thread. The function throws a stack overflow error, and when I try to heap allocate, all of a sudden I can't write to the array. Any tips?
std::array<std::array<std::array<int,3>,400>,225> idk(std::array<std::array<std::array<int,3>,400>,225> pc,const int img_start,const camera &cam,const hittableList &world,const int imageWidth,const int img_end,const int maxDepth,const int samplesPerPixel,bool fml){
auto pic = std::array<std::array<std::array<int,3>,400>,225> {};
for (int i = img_start; i >= img_end; --i) {
color pixelColour(0, 0, 0);
for (int j = 0; j < 400; j++) {
for (int k = 0; k < samplesPerPixel; k++) {
double u = double(j + randomDouble()) / (imageWidth - 1);
double v = double(i + randomDouble()) / (img_start - 1);
ray r = cam.get_ray(u, v);
pixelColour += rayColor(r, world, maxDepth);
}
pic[i][j] = writeColour(pixelColour, maxDepth);
}
}
fml = true;
return pic;
}
std::array<std::array<std::array<int,3>,400>,225>* idk(std::array<std::array<std::array<int,3>,400>,225> pc,const int img_start,const camera &cam,const hittableList &world,const int imageWidth,const int img_end,const int maxDepth,const int samplesPerPixel,bool fml){
auto* pic = new std::array<std::array<std::array<int,3>,400>,225> {};
for (int i = img_start; i >= img_end; --i) {
color pixelColour(0, 0, 0);
for (int j = 0; j < 400; j++) {
for (int k = 0; k < samplesPerPixel; k++) {
double u = double(j + randomDouble()) / (imageWidth - 1);
double v = double(i + randomDouble()) / (img_start - 1);
ray r = cam.get_ray(u, v);
pixelColour += rayColor(r, world, maxDepth);
}
//this line doesnt work the = is underlined and says: no viable overloas '='
pic[i][j] = writeColour(pixelColour, maxDepth);
}
}
fml = true;
return pic;
}
The C++ standard library requires that the payload of std::array has the same storage duration as the std::array itself.
In other words, you are attempting to place 400 * 255 * 3 ints on your stack, and that is above a run-time limit.
A fix is to use a multidimensional array from a third party library like Boost.MultiArray (part of www.boost.org).

How to reorder raw image color data to achieve a specific 2 by 2 format from four images? (C++)

I have the raw color data for four images, let's call them 1, 2, 3, and 4. I am storing the data in an unsigned char * with allocated memory. Individually I can manipulate or encode the images but when trying to concatenate or order them into a single image it works but takes more time than I would like.
I would like to create a 2 by 2 of the raw image data to encode as a single image.
1 2
3 4
For my example each image is 400 by 225 with RGBA (360000 bytes). Iim doing a for loop with memcpy where
for (int j = 0; j < 225; j++)
{
std::memcpy(dest + (j * (400 + 400) * 4), src + (j * 400 * 4), 400 * 4); //
}
for each image with an offset for the starting position added in (the example above would only work for the top left of course).
This works but I'm wondering if this is a solved problem with a better solution, either in an algorithm described somewhere or a small library.
#include <iostream>
const int width = 6;
const int height = 4;
constexpr int n = width * height;
int main()
{
unsigned char a[n], b[n], c[n], d[n];
unsigned char dst[n * 4];
int i = 0, j = 0;
/* init data */
for (; i < n; i++) {
a[i] = 'a';
b[i] = 'b';
c[i] = 'c';
d[i] = 'd';
}
/* re-order */
i = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++, i++, j++) {
dst[i ] = a[j];
dst[i + width] = b[j];
dst[i + n * 2 ] = c[j];
dst[i + n * 2 + width] = d[j];
}
i += width;
}
/* print result */
i = 0;
for (int y = 0; y < height * 2; y++) {
for (int x = 0; x < width * 2; x++, i++)
std::cout << dst[i];
std::cout << '\n';
}
return 0;
}

grayscale Laplace sharpening implementation

I am trying to implement Laplace sharpening using C++ , here's my code so far:
img = imread("cow.png", 0);
Mat convoSharp() {
//creating new image
Mat res = img.clone();
for (int y = 0; y < res.rows; y++) {
for (int x = 0; x < res.cols; x++) {
res.at<uchar>(y, x) = 0.0;
}
}
//variable declaration
int filter[3][3] = { {0,1,0},{1,-4,1},{0,1,0} };
//int filter[3][3] = { {-1,-2,-1},{0,0,0},{1,2,1} };
int height = img.rows;
int width = img.cols;
int filterHeight = 3;
int filterWidth = 3;
int newImageHeight = height - filterHeight + 1;
int newImageWidth = width - filterWidth + 1;
int i, j, h, w;
//convolution
for (i = 0; i < newImageHeight; i++) {
for (j = 0; j < newImageWidth; j++) {
for (h = i; h < i + filterHeight; h++) {
for (w = j; w < j + filterWidth; w++) {
res.at<uchar>(i,j) += filter[h - i][w - j] * img.at<uchar>(h,w);
}
}
}
}
//img - laplace
for (int y = 0; y < res.rows; y++) {
for (int x = 0; x < res.cols; x++) {
res.at<uchar>(y, x) = img.at<uchar>(y, x) - res.at<uchar>(y, x);
}
}
return res;
}
I don't really know what went wrong, I also tried different filter (1,1,1),(1,-8,1),(1,1,1) and the result is also same (more or less). I don't think that I need to normalize the result because the result is in range of 0 - 255. Can anyone explain what really went wrong in my code?
Problem: uchar is too small to hold partial results of filerting operation.
You should create a temporary variable and add all the filtered positions to this variable then check if value of temp is in range <0,255> if not, you need to clamp the end result to fit <0,255>.
By executing below line
res.at<uchar>(i,j) += filter[h - i][w - j] * img.at<uchar>(h,w);
partial result may be greater than 255 (max value in uchar) or negative (in filter you have -4 or -8). temp has to be singed integer type to handle the case when partial result is negative value.
Fix:
for (i = 0; i < newImageHeight; i++) {
for (j = 0; j < newImageWidth; j++) {
int temp = res.at<uchar>(i,j); // added
for (h = i; h < i + filterHeight; h++) {
for (w = j; w < j + filterWidth; w++) {
temp += filter[h - i][w - j] * img.at<uchar>(h,w); // add to temp
}
}
// clamp temp to <0,255>
res.at<uchar>(i,j) = temp;
}
}
You should also clamp values to <0,255> range when you do the subtraction of images.
The problem is partially that you’re overflowing your uchar, as rafix07 suggested, but that is not the full problem.
The Laplace of an image contains negative values. It has to. And you can’t clamp those to 0, you need to preserve the negative values. Also, it can values up to 4*255 given your version of the filter. What this means is that you need to use a signed 16 bit type to store this output.
But there is a simpler and more efficient approach!
You are computing img - laplace(img). In terms of convolutions (*), this is 1 * img - laplace_kernel * img = (1 - laplace_kernel) * img. That is to say, you can combine both operations into a single convolution. The 1 kernel that doesn’t change the image is [(0,0,0),(0,1,0),(0,0,0)]. Subtract your Laplace kernel from that and you obtain [(0,-1,0),(-1,5,-1),(0,-1,0)].
So, simply compute the convolution with that kernel, and do it using int as intermediate type, which you then clamp to the uchar output range as shown by rafix07.

Access violation when reading 2d array C++

My code seems to have a bug somewhere but I just can't catch it. I'm passing a 2d array to three sequential functions. First function populates it, second function modifies the values to 1's and 0's, the third function counts the 1's and 0's. I can access the array easily inside the first two functions, but I get an access violation at the first iteration of the third one.
Main
text_image_data = new int*[img_height];
for (i = 0; i < img_height; i++) {
text_image_data[i] = new int[img_width];
}
cav_length = new int[numb_of_files];
// Start processing - load each image and find max cavity length
for (proc = 0; proc < numb_of_files; proc++)
{
readImage(filles[proc], text_image_data, img_height, img_width);
threshold = makeBinary(text_image_data, img_height, img_width);
cav_length[proc] = measureCavity(bullet[0], img_width, bullet[1], img_height, text_image_data);
}
Functions
int makeBinary(int** img, int height, int width)
{
int threshold = 0;
unsigned long int sum = 0;
for (int k = 0; k < width; k++)
{
sum = sum + img[1][k] + img[2][k] + img[3][k] + img[4][k] + img[5][k];
}
threshold = sum / (width * 5);
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
img[i][j] = img[i][j] > threshold ? 1 : 0;
}
}
return threshold;
}
// Count pixels - find length of cavity here
int measureCavity(int &x, int& width, int &y, int &height, int **img)
{
double mean = 1.;
int maxcount = 0;
int pxcount = 0;
int i = x - 1;
int j;
int pxsum = 0;
for (j = 0; j < height - 2; j++)
{
while (mean > 0.0)
{
for (int ii = i; ii > i - 4; ii--)
{
pxsum = pxsum + img[ii][j] + img[ii][j + 1];
}
mean = pxsum / 4.;
pxcount += 2;
i += 2;
pxsum = 0;
}
maxcount = std::max(maxcount, pxcount);
pxcount = 0;
j++;
}
return maxcount;
}
I keep getting an access violation in the measureCavity() function. I'm passing and accessing the array text_image_data the same way as in makeBinary() and readImage(), and it works just fine for those functions. The size is [550][70], I'm getting the error when trying to access [327][0].
Is there a better, more reliable way to pass this array between the functions?

Alpha-trimmed filter troubles

I am trying to make an alphatrimmed filter in openCV library. My code is not working properly and the resultant image is not looking as image after filtering.
The filter should work in the following way.
Chossing some (array) of pixels in my example it is 9 pixels '3x3' window.
Ordering them in increasing way.
Cutting our 'array' both sides for alpha-2.
calculating arithmetic mean of remaining pixels and inserting them in proper place.
int alphatrimmed(Mat img, int alpha)
{
Mat img9 = img.clone();
const int start = alpha/2 ;
const int end = 9 - (alpha/2);
//going through whole image
for (int i = 1; i < img.rows - 1; i++)
{
for (int j = 1; j < img.cols - 1; j++)
{
uchar element[9];
Vec3b element3[9];
int k = 0;
int a = 0;
//selecting elements for window 3x3
for (int m = i -1; m < i + 2; m++)
{
for (int n = j - 1; n < j + 2; n++)
{
element3[a] = img.at<Vec3b>(m*img.cols + n);
a++;
for (int c = 0; c < img.channels(); c++)
{
element[k] += img.at<Vec3b>(m*img.cols + n)[c];
}
k++;
}
}
//comparing and sorting elements in window (uchar element [9])
for (int b = 0; b < end; b++)
{
int min = b;
for (int d = b + 1; d < 9; d++)
{
if (element[d] < element[min])
{
min = d;
const uchar temp = element[b];
element[b] = element[min];
element[min] = temp;
const Vec3b temporary = element3[b];
element3[b] = element3[min];
element3[min] = temporary;
}
}
}
// index in resultant image( after alpha-trimmed filter)
int result = (i - 1) * (img.cols - 2) + j - 1;
for (int l = start ; l < end; l++)
img9.at<Vec3b>(result) += element3[l];
img9.at<Vec3b>(result) /= (9 - alpha);
}
}
namedWindow("AlphaTrimmed Filter", WINDOW_AUTOSIZE);
imshow("AlphaTrimmed Filter", img9);
return 0;
}
Without actual data, it's somewhat of a guess, but an uchar can't hold the sum of 3 channels. It works modulo 256 (at least on any platform OpenCV supports).
The proper solution is std::sort with a proper comparator for your Vec3b :
void L1(Vec3b a, Vec3b b) { return a[0]+a[1]+a[2] < b[0]+b[1]+b[2]; }