C++ PSNR implementation not matching opencv - c++

The PSNR values I was getting looked a little weird so i decided to compare with openCV. The asnwers do not match and I can't for the life of me figure out why.
double calc_psnr(char* src, char* ref, uint n_pixels) {
char a, b;
double diff, mse, psnr, ssd = 0;;
double psnr1, psnr2, psnr3;
for (auto i = 0; i < n_pixels; i++) {
a = *src++;
b = *ref++;
diff = double(a) - double(b);
ssd += diff * diff;
}
// 20 * log_10(max_f/sqrt(mse)) = 20*(log_10(255) + (-1/2)*log_10(mse)) =
// 48.1308036 - 10*log_10(mse) =
mse = ssd / double(n_pixels);
if (mse == 0) return 100;
psnr = 20 * log10(255 / sqrt(mse)
// These all give the same answer
//psnr1 = 10 * log10((255 * 255) / mse);;
//psnr2 = 20 * log10(255 / sqrt(mse) + std::numeric_limits<double>::epsilon());
//psnr3 = 48.1308036 - 10 * log10(mse);
return psnr;
(In python)
import opencv
d = numpy.zeros((3,3))
c = numpy.zeros((3,3))
d[0] = 10
cv2.PSNR(c,d)
32.90201615587573
const int size = 3;
char img_a[size * size];
char img_b[size * size];
for (int i = 0; i < size * size; i++) {
img_a[i] = 0;
img_b[i] = 0;
}
img_b[0] = 10;
double psnr_test = calc_psnr(img_a, img_b, size * size);
std::cout << "psnr_test: " << psnr_test << endl;
psnr_test: 37.6732
The error is far worse when computing with a full image. Any ideas what the difference could be due to? I checked the opencv codebase but don't see any obvious differences: https://github.com/opencv/opencv/blob/35f1a90df7e5a9b3b275a74868759efd787a8c70/modules/ts/src/ts_func.cpp
Thanks for any help!

Related

C++ Code segmentation fault only in vscode

My C++ code (shown below) works on this site:
GDB Online but not in Visual Studio, where it crashes at
iterations[imag_times][real_times] = i % (iter / 2);
when imag_times is 1 and real_times is 0 with the exception being Exception has occurred. Segmentation fault
I have installed GDB version 7.6.1.
My Question: Does anybody know how to fix that and why this is happening?
#include <iostream>
using namespace std;
int main()
{
// initialization
const double real_min = -1;
const double real_max = 1;
const double imag_min = -1;
const double imag_max = 1;
const int iter = 30;
const double real_offs = 0.01;
const double imag_offs = 0.01;
double z_real = 0;
double z_imag = 0;
double c_real = real_min;
double c_imag = imag_max;
int real_times = 0;
int imag_times = 0;
int** iterations = new int*[1];
iterations[0] = new int;
int i = 0;
// start
while(c_imag >= imag_min)
{
iterations = (int**)realloc(iterations, sizeof(int*) * (imag_times + 1));
real_times = 0;
c_real = real_min;
while(c_real <= real_max)
{
iterations[imag_times] = (int*)realloc(iterations[imag_times], sizeof(int) * (real_times + 1));
z_real = 0;
z_imag = 0;
for(i = 0; i < iter; i++)
{
double z_imag2 = z_imag * z_imag;
z_imag = 2 * z_real * z_imag + c_imag;
z_real = z_real * z_real - z_imag2 + c_real;
if(z_real * z_real + z_imag * z_imag > 4)
{
break;
}
}
iterations[imag_times][real_times] = i % (iter / 2);
real_times++;
c_real = real_min + real_offs * real_times;
}
imag_times++;
c_imag = imag_max - imag_offs * imag_times;
}
// output
for(int i = 0; i < imag_times; i++)
{
for(int j = 0; j < real_times; j++)
{
cout << iterations[i][j];
cout << ",";
}
cout << "\n";
}
cout << "done";
std::cin.get(); // pause so the program doesnt exit instantly
return 0;
}
Thanks in advance!

Issue with a DCT implementation

I have to implement a DCT algorithm in C++, here is my present code :
// dct: computes the discrete cosinus tranform of a 8x8 block
template<typename Tin=uchar,typename Tout=float>
inline cv::Mat_<Tout> dct(const cv::Mat_<Tin>& oBlock) {
int indexNumber;
float pi = 3.14159265359;
float fcoscos, fxy, cos1, cos2, forCos1, forCos2;
cv::Mat_<Tout> resultBloc(8, 8);
for (int u = 0; u < oBlock.rows; u++){
for (int v = 0; v < oBlock.cols; v++){
float cu=0, cv=0, Result=0;
// calcul c(u)
if (u == 0){
cu = (float)sqrt((float)1 / (float)oBlock.rows);
}
else {
cu = (float)sqrt((float)2 / (float)oBlock.rows);
}
// calcul c(v)
if (v == 0){
cv = (float)sqrt((float)1 / (float)oBlock.cols);
}
else {
cv = (float)sqrt((float)2 / (float)oBlock.cols);
}
float sums = 0;
for (int x = 0; x < oBlock.rows; x++){
for (int y = 0; y < oBlock.cols; y++){
indexNumber = x * oBlock.rows + y;
fxy = (int)oBlock.data[indexNumber];
forCos1 = (pi*((2 * x) + 1)*u) / (2 * oBlock.rows);
forCos2 = (pi*((2 * y) + 1)*v) / (2 * oBlock.cols);
cos1 = cos(forCos1);
cos2 = cos(forCos2);
fcoscos = fxy * cos1 * cos2;
sums += fcoscos;
}
}
// calcul total
Result = sums*cu*cv;
indexNumber = u * oBlock.rows + v;
resultBloc.data[indexNumber] = Result;
}
}
return resultBloc;
}
I compared the result with the cv DCT algorithm as follow :
cv::Mat_<float> tempImage(8,8);
for (int i = 0; i < vecImageCut[0].cols*vecImageCut[0].rows; i++){
tempImage.data[i] = (int)vecImageCut[0].data[i];
}
cv::Mat_<float> dctCV;
cv::dct(tempImage, dctCV);
for (int i = 0; i < blocksAfterDCT[0].cols*blocksAfterDCT[0].rows; i++){
std::cerr << "Difference DCT for pixel " << i << " : " << dctCV.data[i] - blocksAfterDCT[0].data[i] << std::endl;
}
The results between my DCT and the cv DCT are very different so i assume my DCT algorithm is wrong but i searched for hours and i can't find my mistake, can anyone tell me where i did something wrong ?
Your index calculations are wrong. In indexNumber = x * oBlock.rows + y;, since x is counting rows it needs to be multiplied by the number of columns:
indexNumber = x * oBlock.cols + y;
The same for indexNumber = u * oBlock.rows + v;
indexNumber = u * oBlock.cols + v;

How to implement midpoint displacement

I'm trying to implement procedural generation in my game. I want to really grasp and understand all of the algorithms nessecary rather than simply copying/pasting existing code. In order to do this I've attempted to implement 1D midpoint displacement on my own. I've used the information here to write and guide my code. Below is my completed code, it doesn't throw an error but that results don't appear correct.
srand(time(NULL));
const int lineLength = 65;
float range = 1.0;
float displacedLine[lineLength];
for (int i = 0; i < lineLength; i++)
{
displacedLine[i] = 0.0;
}
for (int p = 0; p < 100; p++)
{
int segments = 1;
for (int i = 0; i < (lineLength / pow(2, 2)); i++)
{
int segs = segments;
for (int j = 0; j < segs; j++)
{
int x = floor(lineLength / segs);
int start = (j * x) + 1;
int end = start + x;
if (i == 0)
{
end--;
}
float lo = -range;
float hi = +range;
float change = lo + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (hi - lo)));
int center = ((end - start) / 2) + start;
displacedLine[center - 1] += change;
segments++;
}
range /= 2;
}
}
Where exactly have I made mistakes and how might I correct them?
I'm getting results like this:
But I was expecting results like this:
The answer is very simple and by the way I'm impressed you managed to debug all the potential off-by-one errors in your code. The following line is wrong:
displacedLine[center - 1] += change;
You correctly compute the center index and change amount but you missed that the change should be applied to the midpoint in terms of height. That is:
displacedLine[center - 1] = (displacedLine[start] + displacedLine[end]) / 2;
displacedLine[center - 1] += change;
I'm sure you get the idea.
The problem seems to be that you are changing only the midpoint of each line segment, rather than changing the rest of the line segment in proportion to its distance from each end to the midpoint. The following code appears to give you something more like what you're looking for:
#include <iostream>
#include <cstdlib>
#include <math.h>
#include <algorithm>
using namespace std;
void displaceMidPt (float dline[], int len, float disp) {
int midPt = len/2;
float fmidPt = float(midPt);
for (int i = 1; i <= midPt; i++) {
float ptDisp = disp * float(i)/fmidPt;
dline[i] += ptDisp;
dline[len-i] += ptDisp;
}
}
void displace (float displacedLine[], int lineLength, float range) {
for (int p = 0; p < 100; p++) {
int segs = pow(p, 2);
for (int j = 0; j < segs; j++) {
float lo = -range;
float hi = +range;
float change = lo + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (hi - lo)));
int start = int(float(j)/float(segs)*float(lineLength));
int end = int(float(j+1)/float(segs)*float(lineLength));
displaceMidPt (displacedLine+start,end-start,change);
}
range /= 2;
}
}
void plot1D (float x[], int len, int ht = 10) {
float minX = *min_element(x,x+len);
float maxX = *max_element(x,x+len);
int xi[len];
for (int i = 0; i < len; i++) {
xi[i] = int(ht*(x[i] - minX)/(maxX - minX) + 0.5);
}
char s[len+1];
s[len] = '\0';
for (int j = ht; j >= 0; j--) {
for (int i = 0; i < len; i++) {
if (xi[i] == j) {
s[i] = '*';
} else {
s[i] = ' ';
}
}
cout << s << endl;
}
}
int main () {
srand(time(NULL));
const int lineLength = 65;
float range = 1.0;
float displacedLine[lineLength];
for (int i = 0; i < lineLength; i++) {
displacedLine[i] = 0.0;
}
displace (displacedLine,lineLength,range);
plot1D (displacedLine,lineLength);
return 0;
}
When run this way, it produces the following result:
$ c++ -lm displace.cpp
$ ./a
*
* *
* ***
* * * *
* ** **** * **
* *** **** * * * ** *
* * ** ** *** * * * *
** ** *
* * * ***
** ***
*

C++ Segmentation Fault OpenCV

The idea in the following code is to have a bunch of "wanderer" objects that slowly "paint" an image onto a canvas. The problem is, that this code only seems to working on square images (in the code, the square image is identified as "hidden" (because it is unveiled by the "painters") and it is loaded in from the file called "UncoverTest.png"), not rectangular ones, which is mysterious to me. I get a segmentation fault error when trying to work with anything but a square. As far as I can tell, the segmentation fault error emerges when I enter the loop to iterate through the vector of type Agent (at the line for (vector<Agent>::iterator iter = agents.begin(); iter != agents.end();++iter)).
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;
//#define WINDOW_SIZE 500
#define STEP_SIZE 10.0
#define NUM_AGENTS 100
/********************/
/* Agent class definition and class prototypes */
/********************/
class Agent {
public:
Agent();
int * GetLocation(void);
void Move(void);
void Draw(Mat image);
int * GetSize(void);
private:
double UnifRand(void);
int * location;
int * GetReveal(void);
Mat hidden;
};
int * Agent::GetSize(void) {
int * size = new int[2];
size[0] = hidden.cols;
size[1] = hidden.rows;
return (size);
}
int * Agent::GetReveal(void) {
int * BGR = new int[3];
location = GetLocation();
for (int i = 0; i < 3; i++) {
BGR[i] = hidden.data[hidden.step[0]*location[0] + hidden.step[1]*location[1] + i];
}
return (BGR);
}
void Agent::Draw(Mat image) {
int * location = GetLocation();
int * color = GetReveal();
for (int i = 0;i < 3;i++) {
image.data[image.step[0]*location[0] + image.step[1]*location[1] + i] = color[i];
}
}
void Agent::Move(void) {
int dx = (int)(STEP_SIZE*UnifRand() - STEP_SIZE/2);
int dy = (int)(STEP_SIZE*UnifRand() - STEP_SIZE/2);
location[0] += (((location[0] + dx >= 0) & (location[0] + dx < hidden.cols)) ? dx : 0);
location[1] += (((location[1] + dy >= 0) & (location[1] + dy < hidden.rows)) ? dy : 0);
}
Agent::Agent() {
location = new int[2];
hidden = imread("UncoverTest.png",1);
location[0] = (int)(UnifRand()*hidden.cols);
location[1] = (int)(UnifRand()*hidden.rows);
}
double Agent::UnifRand(void) {
return (rand()/(double(RAND_MAX)));
}
int * Agent::GetLocation(void) {
return (location);
}
/********************/
/* Function prototypes unrelated to the Agent class */
/********************/
void DrawAgents(void);
/********************/
/* Main function */
/********************/
int main(void) {
DrawAgents();
return (0);
}
void DrawAgents(void) {
vector<Agent> agents;
int * size = new int[2];
Mat image;
for (int i = 0; i < NUM_AGENTS; i++) {
Agent * a = new Agent();
agents.push_back(* a);
if (i == 0) {
size = (* a).GetSize();
}
}
// cout << size[0] << " " << size[1] << endl;
image = Mat::zeros(size[0],size[1],CV_8UC3);
cvNamedWindow("Agent Example",CV_WINDOW_AUTOSIZE);
cvMoveWindow("Agent Example",100,100);
for (int stop = 1;stop != 27;stop = cvWaitKey(41)) {
for (vector<Agent>::iterator iter = agents.begin(); iter != agents.end();++iter) {
(* iter).Move();
(* iter).Draw(image);
} imshow("Agent Example",image);
}
}
Can anyone explain to me how this error arises with square images only and how the problem might be fixed?
I don't fully understand your code but as per your last comment, "stepping of the canvas" i think i can see that you have a couple of situations where you might be trying to access data out of range in both your "hidden" mat and "image" mats.
Afraid i can only offer sugestions
void Agent::Draw(Mat image) {
int * location = GetLocation();
int * color = GetReveal();
for (int i = 0;i < 3;i++) {
image.data[image.step[0]*location[0] + image.step[1]*location[1] + i] = color[i];
}
}
Here your accessing GetLocation which has been instantiated from a random number times the size of the hidden mat during the construction of the Agent. I would worry that here your going to get an "index out of bounds" type error when accessing the image.data matrix. So this might be the first thing to check.
Like wise in
int * Agent::GetReveal(void) {
int * BGR = new int[3];
location = GetLocation();
for (int i = 0; i < 3; i++) {
BGR[i] = hidden.data[hidden.step[0]*location[0] + hidden.step[1]*location[1] + i];
}
return (BGR);
}
you using getLocation() which is going to return a point far larger than the size of the hidden image. So i'm pretty sure you get an error here as well. location should be derived from the hidden.cols() and hidden.rows().
Only had a glancing look, but i would definitely put some checks in around the values getLocation() is returning, and if such a value is accessible from the mat matrices.
Additionally, although i'm not entirely sure, as i think your using location in two different ways, but if location is a point somewhere in your Draw(image) then you would need to adjust the following:
location[0] += (((location[0] + dx >= 0) & (location[0] + dx < hidden.cols)) ? dx : 0);
location[1] += (((location[1] + dy >= 0) & (location[1] + dy < hidden.rows)) ? dy : 0);
and take into account the width of the hidden image, something like
location[0] += (((location[0] + dx >= 0) & (location[0] + dx + hidden.cols < maxWidth)) ? dx : 0);
location[1] += (((location[1] + dy >= 0) & (location[1] + dy + hidden.rows < maxHeight)) ? dy : 0);
where maxWidth and maxHeight are the width of your image.
Hope that gets you on the right track.
If you are in a Linux environment, you can use valgrind to find out exactly where the segmentation fault is happening. Just type valgrind before the name of the program, or the way you execute your program. For example, if you execute your program with the following command:
hello -print
issue the following command instead:
valgrind hello -print

My Particle Swarm Optimization code generates different answers in C++ and MATLAB

I have written a global version of Particle Swarm Optimization algorithm in C++.
I tried to write it exactly as same as my MATLAB PSO code that have written before, but this code generates different and so worst answers.
The MATLAB code is:
clear all;
numofdims = 30;
numofparticles = 50;
c1 = 2;
c2 = 2;
numofiterations = 1000;
V = zeros(50, 30);
initialpop = V;
Vmin = zeros(30, 1);
Vmax = Vmin;
Xmax = ones(30, 1) * 100;
Xmin = -Xmax;
pbestfits = zeros(50, 1);
worsts = zeros(50, 1);
bests = zeros(50, 1);
meanfits = zeros(50, 1);
pbests = zeros(50, 30);
initialpop = Xmin + (Xmax - Xmin) .* rand(numofparticles, numofdims);
X = initialpop;
fitnesses = testfunc1(X);
[minfit, minfitidx] = min(fitnesses);
gbestfit = minfit;
gbest = X(minfitidx, :);
for i = 1:numofdims
Vmax(i) = 0.2 * (Xmax(i) - Xmin(i));
Vmin(i) = -Vmax(i);
end
for t = 1:1000
w = 0.9 - 0.7 * (t / numofiterations);
for i = 1:numofparticles
if(fitnesses(i) < pbestfits(i))
pbestfits(i) = fitnesses(i);
pbests(i, :) = X(i, :);
end
end
for i = 1:numofparticles
for j = 1:numofdims
V(i, j) = min(max((w * V(i, j) + rand * c1 * (pbests(i, j) - X(i, j))...
+ rand * c2 * (gbest(j) - X(i, j))), Vmin(j)), Vmax(j));
X(i, j) = min(max((X(i, j) + V(i, j)), Xmin(j)), Xmax(j));
end
end
fitnesses = testfunc1(X);
[minfit, minfitidx] = min(fitnesses);
if(minfit < gbestfit)
gbestfit = minfit;
gbest = X(minfitidx, :);
end
worsts(t) = max(fitnesses);
bests(t) = gbestfit;
meanfits(t) = mean(fitnesses);
end
In which, testfunc1 is:
function [out] = testfunc1(R)
out = sum(R .^ 2, 2);
end
The C++ code is:
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <ctime>
#define rand_01 ((float)rand() / (float)RAND_MAX)
const int numofdims = 30;
const int numofparticles = 50;
using namespace std;
void fitnessfunc(float X[numofparticles][numofdims], float fitnesses[numofparticles])
{
memset(fitnesses, 0, sizeof (float) * numofparticles);
for(int i = 0; i < numofparticles; i++)
{
for(int j = 0; j < numofdims; j++)
{
fitnesses[i] += (pow(X[i][j], 2));
}
}
}
float mean(float inputval[], int vallength)
{
int addvalue = 0;
for(int i = 0; i < vallength; i++)
{
addvalue += inputval[i];
}
return (float)(addvalue / vallength);
}
void PSO(int numofiterations, float c1, float c2,
float Xmin[numofdims], float Xmax[numofdims], float initialpop[numofparticles][numofdims],
float worsts[], float meanfits[], float bests[], float *gbestfit, float gbest[numofdims])
{
float V[numofparticles][numofdims] = {0};
float X[numofparticles][numofdims];
float Vmax[numofdims];
float Vmin[numofdims];
float pbests[numofparticles][numofdims];
float pbestfits[numofparticles];
float fitnesses[numofparticles];
float w;
float minfit;
int minfitidx;
memcpy(X, initialpop, sizeof(float) * numofparticles * numofdims);
fitnessfunc(X, fitnesses);
minfit = *min_element(fitnesses, fitnesses + numofparticles);
minfitidx = min_element(fitnesses, fitnesses + numofparticles) - fitnesses;
*gbestfit = minfit;
memcpy(gbest, X[minfitidx], sizeof(float) * numofdims);
for(int i = 0; i < numofdims; i++)
{
Vmax[i] = 0.2 * (Xmax[i] - Xmin[i]);
Vmin[i] = -Vmax[i];
}
for(int t = 0; t < 1000; t++)
{
w = 0.9 - 0.7 * (float) (t / numofiterations);
for(int i = 0; i < numofparticles; i++)
{
if(fitnesses[i] < pbestfits[i])
{
pbestfits[i] = fitnesses[i];
memcpy(pbests[i], X[i], sizeof(float) * numofdims);
}
}
for(int i = 0; i < numofparticles; i++)
{
for(int j = 0; j < numofdims; j++)
{
V[i][j] = min(max((w * V[i][j] + rand_01 * c1 * (pbests[i][j] - X[i][j])
+ rand_01 * c2 * (gbest[j] - X[i][j])), Vmin[j]), Vmax[j]);
X[i][j] = min(max((X[i][j] + V[i][j]), Xmin[j]), Xmax[j]);
}
}
fitnessfunc(X, fitnesses);
minfit = *min_element(fitnesses, fitnesses + numofparticles);
minfitidx = min_element(fitnesses, fitnesses + numofparticles) - fitnesses;
if(minfit < *gbestfit)
{
*gbestfit = minfit;
memcpy(gbest, X[minfitidx], sizeof(float) * numofdims);
}
worsts[t] = *max_element(fitnesses, fitnesses + numofparticles);
bests[t] = *gbestfit;
meanfits[t] = mean(fitnesses, numofparticles);
}
}
int main()
{
time_t t;
srand((unsigned) time(&t));
float xmin[30], xmax[30];
float initpop[50][30];
float worsts[1000], bests[1000];
float meanfits[1000];
float gbestfit;
float gbest[30];
for(int i = 0; i < 30; i++)
{
xmax[i] = 100;
xmin[i] = -100;
}
for(int i = 0; i < 50; i++)
for(int j = 0; j < 30; j++)
{
initpop[i][j] = rand() % (100 + 100 + 1) - 100;
}
PSO(1000, 2, 2, xmin, xmax, initpop, worsts, meanfits, bests, &gbestfit, gbest);
cout<<"fitness: "<<gbestfit<<endl;
return 0;
}
I have debugged two codes many times but can not find the difference which makes answers different.
It is making me crazy!
May you help me please?
Update:
Please consider that, the function mean is just used for reporting some information and is not used in the optimization procedure.
You've got integer division in the following line
w = 0.9 - 0.7 * (float) (t / numofiterations);
w will be 0.2 for every iteration, change it to
w = 0.9 - 0.7 * t / numofiterations;
The first multiplication will automatically promote t to a double the division should then promote numof iterations to a double.
The parenthesis means it will be done first and therefore not be promoted as wo integers is involved in the division.
This could be a mistake in function mean:
return (float)(addvalue / vallength);
This is integer division, so the result is truncated down, then cast to float. It is unlikely this is what you want.