Let's say that I have an array called image which is a long contiguous array of "size" elements - as defined bellow.
I'd like to crop this array (then getting a sub matrix) then, by modifying the sub array I'll automatically modify the source image (reference).
Be aware that the crop operation will return a non-contiguous array. This is in fact the problem.
Is there a way to do this elegantly in C++?
By the way, I'm not interested by using OpenCV, boost, etc...
thanks for your help.
template <class Type> class Image
{
private:
Type *image;
public:
int rows;
int cols;
int size;
Image(int rows, int cols): rows(rows), cols(cols)
{
image = new Type[size = rows*cols];
}
~Image()
{
delete [] image;
}
Type & at(int i, int j)
{
return image[cols*i + j];
}
void print()
{
for(int i = 0; i < rows; ++i)
{
for(int j = 0; j < cols; ++j)
cout << at(i,j) << " ";
cout << endl;
}
cout << endl;
}
};
You can create a class CroppedImage that holds a reference or pointer to the original Image and offsets and provides its own methods, which add the offsets and then invoke the original images methods:
template <class Type> class CroppedImage
{
private:
Image<Type> *original;
int offsetX;
int offsetY;
public:
int rows;
int cols;
int size;
CroppedImage(Image<Type> *orig, int offX, int offY, int width, int height)
{
original = orig;
offsetX = offX;
offsetY = offY;
rows = height;
cols = width;
size = rows*cols;
}
~CroppedImage(){}
Type & at(int i, int j)
{
return original->at(i+offsetX, j+offsetY);
}
void print()
{
for(int i = 0; i < rows; ++i)
{
for(int j = 0; j < cols; ++j)
cout << at(i,j) << " ";
cout << endl;
}
cout << endl;
}
}
I haven't tested it, there might be some typos and other errors.
If you don't want to create a new class, you can incorporate the code into your Image class.
Related
I have made a class called matrix that stores values in a 1D array, but outputs it as a 2D array. I have included print statements to show the exact values supposedly being put into the array however when I use the print function to index it, it shows incorrect value on the second row last index. not entirely sure what I'm doing wrong.
#include <iostream>
class Matrix
{
private:
int rows{}, cols{};
double *newArr;
public:
Matrix(int row, int col)
{
rows = row;
cols = col;
newArr = new double[rows * cols];
}
void setValue(int row, int col, double value)
{
std::cout << value << std::endl;
newArr[row * row + col] = value;
}
double getValue(int row, int col)
{
return newArr[row * row + col];
}
int getRows()
{
return rows;
}
int getCols()
{
return cols;
}
void print()
{
for (int i{}; i < rows; ++i){
for (int j{}; j < cols; ++j){
std::cout << newArr[i * i + j] << " ";
}
std::cout << std::endl;
}
}
~Matrix()
{
delete[] newArr;
}
};
int main()
{
Matrix x(3, 4);
for (int i{}; i < x.getRows(); i++){
for (int j{}; j < x.getCols(); j++){
x.setValue(i, j, (j+i)/2.0);
}
std::cout << std::endl;
}
std::cout << std::endl;
x.print();
return 0;
}
I changed your indexing logic and it seems okay.
Still not getting why you use row * row + col instead of row * cols + col.
Dynamic allocated the size of the matrix and layout the 2d matrix into 1d. Then you should use the length to fill the array, not (row index)^2.
Live Demo
#include <iostream>
class Matrix
{
private:
int rows{}, cols{};
double *newArr;
public:
Matrix(int row, int col)
{
rows = row;
cols = col;
newArr = new double[rows * cols];
}
void setValue(int row, int col, double value)
{
std::cout << value << std::endl;
newArr[row * cols + col] = value;
}
double getValue(int row, int col)
{
return newArr[row * cols + col];
}
int getRows()
{
return rows;
}
int getCols()
{
return cols;
}
void print()
{
for (int i{}; i < rows; ++i){
for (int j{}; j < cols; ++j){
std::cout << newArr[i * cols + j] << " ";
}
std::cout << std::endl;
}
}
~Matrix()
{
delete[] newArr;
}
};
int main()
{
Matrix x(3, 4);
for (int i{}; i < x.getRows(); i++){
for (int j{}; j < x.getCols(); j++){
x.setValue(i, j, (j+i)/2.0);
}
std::cout << std::endl;
}
std::cout << std::endl;
x.print();
return 0;
}
I wrote simple program to calculate some Matrix, and stuck at this problem. I can't get out my new Matrix.
This is my Matrix.h
#pragma once
using namespace std;
class Matrix
{
private:
int row, col;
float **matrix;
public:
Matrix(int); // square matrix
Matrix(int, int); // matrix with different rows and columns
~Matrix(); //delete
void set(int, int, double); // set value to matrix
double get(int, int); // get value from matrix
void print(); // display matrix
int rows(); // show rows
int cols(); //show columns
Matrix operator*(Matrix); // multiply matrix
};
#include <iostream>
#include <fstream>
#include "Matrix.h"
using namespace std;
Matrix::Matrix(int row) {
if (row <= 0) {
cout << "To small value for ROW or COL";
exit(0);
}
this->row = row;
this->col = row;
this->matrix = new float* [row];
for (int i = 0; i < row; i++)
{
this->matrix[i] = new float[row];
for (int j = 0; j < row; j++)
{
this->matrix[i][j] = 0;
}
}
}
Matrix::Matrix(int row, int col) {
if (row <= 0 || col <= 0) {
cout << "To small value for ROW or COL";
exit(0);
}
this->row = row;
this->col = col;
this->matrix = new float* [row];
for (int i = 0; i < row; i++)
{
this->matrix[i] = new float[col];
for (int j = 0; j < col; j++)
{
this->matrix[i][j] = 0;
}
}
}
Matrix::~Matrix() {
for (int i = 0; i < this->row; i++)
{
delete[] matrix[i];
}
delete[] matrix;
}
int Matrix::rows() {
return this->row;
}
int Matrix::cols() {
return this->col;
}
void Matrix::set(int row, int col, double val) {
if (row > this->row || col > this->col || row < 0 || col < 0) {
cout << "There is no value to set.";
exit(0);
}
else {
this->matrix[row - 1][col - 1] = val;
}
}
double Matrix::get(int row, int col) {
if (row > this->row || col > this->col || row < 0 || col < 0) {
cout << "There is no value, please correct ROW or COL.";
exit(0);
}
else {
cout << "Taken value from row " << row << " and col " << col << " = ";
return this->matrix[row - 1][col - 1];
}
}
void Matrix::print() {
for (int i = 0; i < this->row; i++)
{
for (int j = 0; j < this->col; j++)
{
cout << this->matrix[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
Matrix Matrix::operator*(Matrix B) {
Matrix multiplied(B.row, this->col);
for (int i = 0; i < this->row; i++) {
for (int j = 0; j < B.col; j++) {
multiplied.matrix[i][j] = 0;
for (int k = 0; k < this->col; k++) {
multiplied.matrix[i][j] += this->matrix[i][k] * B.matrix[k][j];
}
}
}
multiplied.print(); // this work, and show correct answer in console
return multiplied;
}
#include <iostream>
#include <fstream>
#include "Matrix.h"
using namespace std;
int main()
{
Matrix one(8,7), two(8,7), three(1,1), four(5);
one.set(1, 1, 5);
cout << one.get(1,5) << endl;
one.print();
two.set(1,2,2);
two.print();
Matrix nine = two * one; // but two*one from Matrix.cpp gives me correct Matrix
nine.print(); // this stop the program
}
I'm getting something like this:
makefile:4: recipe for target 'run' failed
make: *** [run] Segmentation fault (core dumped)
I'm using makefile to run this code. Where is the problem?
A comment on your question pinpoints the reason why things are failing - You did not define a copy constructor, so the compiler implicitly defines one for you. The implicit copy constructor copies your matrix pointer into a new Matrix, and then it gets deleted both inside operator*() call and outside where the new matrix is returned. You can fix it by defining copy and move constructors, but I think there's something much better.
First of all, if you find yourself using new and delete manually in your code, it's usually wrong in modern C++. Secondly, you don't need to allocate new arrays for each row - they are all going to be the same size, and you can do one single allocation.
#pragma once
#include <vector>
// never use namespace aliases in header files - this polutes the global namespace of every user.
class Matrix
{
private:
size_t rows; // unsigned integers prevent values less than 0
size_t cols;
std::vector<double> elements;
public:
Matrix(size_t);
Matrix(size_t, size_t);
// destructor no longer needed! vector handles it
void set(size_t, size_t, double);
double get(size_t, size_t) const; // follow const correctness
void print();
size_t rows();
size_t cols();
Matrix operator*(Matrix);
};
Some implementations:
// This is the whole constructor. Vector will zero-initialize all the values
Matrix::Matrix(size_t row, size_t col)
: rows(row)
, cols(col)
, elements(row * col)
{ }
void Matrix::set(size_t row, size_t col, double val) {
elements[row * cols + col] = val;
}
double Matrix::get(size_t row, size_t col) const {
return elements[row * cols + col];
}
So i have an abstract class named Matrice containing a matrix of complex numbers
class Matrice {
Complex** v; //matrix
public:
Matrice() {
v = new Complex * [//lin]; //use size here, without declaring it here
for (int i = 0; i < //lin; i++) {
v[i] = new Complex[//col];
for (int j = 0; j < //col; j++)
cin >> v[i][j];
}
}
virtual void afisare(int lin, int col) {
for (int i = 0; i < lin; i++) {
for (int j = 0; j < col; j++)
cout << v[i][j] << " ";
cout << endl;
}
}
};
and it's derived class
class Matrice_oarecare :Matrice {
int lin, col; //the size i want to use
public:
Matrice_oarecare();
~Matrice_oarecare() {
}
void afisare() { Matrice::afisare(lin, col); }
};
the question is how do i dynamically allocate my matrix using the size specified in my derived class Matrice_oarecare, sorry for the dumb question but i'm new to this inheritance thing
If Matrice_oarecare inherits from Matrice, it has visibility on all protected attributes of Matrice class.
If you want to have access to Complex**v from the derived class then
Complex**v should protected in the base class.
and to allocate in Matrice_oarecare:
v = new Complex*[lin];
for(int i = 0; i < lin; ++i)
v[i] = new Complex[col];
Alternative
You can have a function called allocatein the base class that allocates the Complex** array like so :
class Matrice{
void allocate(int rows, int cols){
v = new Complex*[rows];
for(int i = 0; i < rows; ++i)
v[i] = new Complex[cols];
}
}
and call it from the constructor of the derived class. So you will have
class Matrice_oarecare :Matrice {
int lin, col;
public:
Matrice_oarecare(int rows, int cols):lin(rows),col(cols){
Matrice::allocate(lin, col);
}
~Matrice_oarecare() {
}
void afisare() { Matrice::afisare(lin, col); }
};
also you can have linand col taken as parameters to the contructor of Matrice
Why not just overload the constructor?
You can pass the parameters of the derived constructor to the base_class constructor and than use those parameters as you see fit.
class Matrice {
Complex** v; //matrix
public:
Matrice(int lin, int cols) {
v = new Complex * [lin]; //use size here, without declaring it here
for (int i = 0; i < lin; i++) {
v[i] = new Complex[cols];
for (int j = 0; j < cols; j++)
cin >> v[i][j];
}
}
virtual void afisare(int lin, int col) {
for (int i = 0; i < lin; i++) {
for (int j = 0; j < col; j++)
cout << v[i][j] << " ";
cout << endl;
}
}
};
class Matrice_oarecare :Matrice {
int lin, col; //the size i want to use
public:
Matrice_oarecare():
Matrice(lin, col) {};
~Matrice_oarecare() {}
void afisare() { Matrice::afisare(lin, col); }
};
The task is as follows: Describe the class "matrix of numbers" with component data: the dimensions of the matrix, a pointer to the elements. Overload operations: << (matrix output to the screen), + (addition of matrices), unary ¬– (change the sign of each element), / = (divide each element by a number). I performed it, and performed it correctly, but you need to set the matrix dimension from the keyboard, and as you can see, it is set in advance for me [3] [3]. It sounds pretty simple, but something I'm really dumb. Thanks in advance for your help. Here is the code:
#include "pch.h"
#include <iostream>
using namespace std;
class Matrix
{
public:
Matrix()
{
int Table[3][3];
}
int Table[3][3];
void Create()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
Table[i][j] = 10;
}
};
ostream& operator <<(ostream& t, Matrix a)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
t << a.Table[i][j] << " ";
t << "\n";
}
return t;
}
Matrix& operator /=(Matrix& a, int num)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] /= num;
return a;
}
Matrix& operator -(Matrix& a, int empty)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] = -a.Table[i][j];
return a;
}
Matrix& operator +(Matrix& a, Matrix b)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] += b.Table[i][j];
return a;
}
int main()
{
int u;
setlocale(LC_ALL, "Russian");
Matrix Example;
Example.Create();
Matrix Example1;
Example1.Create();
cout << Example;
cout << Example1;
cout << "Сумма матриц: "<<endl;
cout << Example + Example1;
Example - 1;
Example1 - 1;
cout<< Example + Example1;
cout << "На сколько вы хотите её поделить?\n";
cin >> u;
Example /= u;
Example1 /= u;
cout << Example;
cout << Example1;
}`
You need to dynamically create the matrix.
In order to this you need to use pointers(*). Change int table[3][3]
double table**;
An example of how it could be implemented (note that I use matrix instead of table)
class Matrix {
private:
double** matrix;
int col;
int row;
public:
Matrix(){};
void Create(int row, int col);
};
void Matrix::Create(int row_, int col_){
double val = 0.0;
col = col_; // initalize private members
row = row_;
matrix = new double*[row]; // Create a new array of size row_
for(int i = 0; i < row; i++)
{
matrix[i] = new double[col]; // Create new cols of size col (inside array of row)
}
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
{
matrix[i][j] = val;
val = val + 1.0;
}
}
}
I tried to reuse your design for simplicity, but I really suggest that you try to specify the dimensions of the matrix in a constructor instead and maybe even construct the matrix in it as well.
Something like this:
Matrix(int row_, int col_) : row(row_), col(col_) {*/ create matrix here /*};
You can skip the "create matrix here" part and use your own Create() if you want to.
You need dynamic memory allocation for that. I won't fiddle around with pointers (new / delete) unless you are explicitly told to. As a beginner you should probably use the standard template library (STL) tools:
#include <vector> and use std::vector<std::vector<int>> Table instead of int Table[3][3]. Then write a constructor like this:
Matrix(std::size_t rows, std::size_t cols)
{
Table.resize(rows);
for (unsigned int i = 0; i < Table.size(); ++i)
Table[i].resize(cols);
}
You can additionally store the dimension of the matrix, but there is no need to do it since you can get the information from the vectors. Replace the hardcoded dimensions in all loops by the corresponding dynamic sizes (stored or extracted from the vectors). For example:
Matrix& operator +(Matrix& a, Matrix b)
{
unsigned int rows = a.Table.size();
unsigned int cols = a.Table[0].size();
for (unsigned int i = 0; i < rows; i++)
for (unsigned int j = 0; j < cols; j++)
a.Table[i][j] += b.Table[i][j];
return a;
}
However, this vector of vectors is not really effective. Better would be a single vector but I guess for a beginner it is okay.
Greetings
I'm new to C++ and currently I'm trying to implement 2D matrix from classes, this is my current code, right now I'm unable to create an instance of the matrix object, please leave me feedback what I need to fix.
*Updated: I have fixed some of the code, but the matrix doesn't print anything
#include <iostream>
#include <cstdlib>
using namespace std;
class Matrix
{
public:
Matrix(); //Default constructor
Matrix(int *row, int *col); //Main constructor
void setVal(int row, int col, int val); //Method to set the val of [i,j]th-entry
void printMatrix(); //Method to display the matrix
~Matrix(); //Destructor
private:
int row, col;
double **matrix;
//allocate the array
void allocArray()
{
matrix = new double *[*row];
for (int count = 0; count < *row; count++)
*(matrix + count) = new double[*col];
}
};
//Default constructor
Matrix::Matrix() : Matrix(0,0) {}
//Main construcor
Matrix::Matrix(int *row, int *col)
{
allocArray();
for (int i=0; i < *row; i++)
{
for (int j=0; j < *col; j++)
{
*(*(matrix + i) + j) = 0;
}
}
}
//destructor
Matrix::~Matrix()
{
for( int i = 0 ; i < row ; i++ )
delete [] *(matrix + i) ;
delete [] matrix;
}
//SetVal function
void Matrix::setVal(int row, int col, int val)
{
matrix[row][col] = val;
}
//printMatrix function
void Matrix::printMatrix()
{
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
cout << *(*(matrix + i) + j) << "\t";
cout << endl;
}
}
int main()
{
int d1 = 2;
int d2 = 2;
//create 4x3 dynamic 2d array
Matrix object(&d1,&d2);
object.printMatrix();
return 0;
}
Your line
Matrix object = new int **Matrix(d1,d2);
is wrong. Use simply
Matrix object(d1,d2);
no need for Java-like syntax which in fact in C++ means dynamic allocation: Matrix* object = new Matrix(d1,d2);
Instead of Matrix object = new int **Matrix(d1,d2); use Matrix* object = new Matrix(d1,d2);
Also, you will have to use object->printMatrix(); instead of object.printMatrix();