How to Calculate PSNR in ns3

To calculate the Peak Signal-to-Noise Ratio (PSNR) in ns3, we need to compute the frequently used metrics PSNR by measuring the quality of reconstruction of lossy compression codecs. This is usually used in both image and video compressor. To compute the PSNR, we required the Mean Squared Error (MSE) among the innovative and the reconstructed signal.

Here we provide the procedures to calculate the PSNR in ns3:

  1. Set up the Simulation: Simulate a network scenario where data is transmitted and received. This can be done using UDP or TCP.
  2. Collect the Original and Received Data: Capture the data sent and received during the simulation.
  3. Calculate Mean Squared Error (MSE): Compute the MSE between the original and received data.
  4. Calculate PSNR: Use the MSE to calculate the PSNR.

Example Implementation

Below is the samples snippet in ns3 to configure the basic networks and compute the PSNR. This sample adopts the access to the original and the obtained data that can obtains the application layer.

Setting Up the Network Simulation

#include “ns3/core-module.h”

#include “ns3/network-module.h”

#include “ns3/internet-module.h”

#include “ns3/point-to-point-module.h”

#include “ns3/applications-module.h”

#include <cmath>

using namespace ns3;

NS_LOG_COMPONENT_DEFINE(“PSNRExample”);

// Function to calculate Mean Squared Error (MSE)

double calculateMSE(const std::vector<uint8_t>& original, const std::vector<uint8_t>& received) {

double mse = 0.0;

size_t dataSize = std::min(original.size(), received.size());

for (size_t i = 0; i < dataSize; ++i) {

mse += std::pow(static_cast<double>(original[i] – received[i]), 2);

}

mse /= dataSize;

return mse;

}

// Function to calculate PSNR

double calculatePSNR(const std::vector<uint8_t>& original, const std::vector<uint8_t>& received) {

double mse = calculateMSE(original, received);

if (mse == 0) {

return std::numeric_limits<double>::infinity(); // Perfect match

}

double maxPixelValue = 255.0;

double psnr = 10 * std::log10((maxPixelValue * maxPixelValue) / mse);

return psnr;

}

int main(int argc, char *argv[]) {

// Set up the default simulation parameters

Time::SetResolution(Time::NS);

LogComponentEnable(“PSNRExample”, LOG_LEVEL_INFO);

// Create nodes

NodeContainer nodes;

nodes.Create(2);

// Set up the point-to-point link

PointToPointHelper pointToPoint;

pointToPoint.SetDeviceAttribute(“DataRate”, StringValue(“5Mbps”));

pointToPoint.SetChannelAttribute(“Delay”, StringValue(“2ms”));

NetDeviceContainer devices;

devices = pointToPoint.Install(nodes);

// Install the Internet stack

InternetStackHelper stack;

stack.Install(nodes);

Ipv4AddressHelper address;

address.SetBase(“10.1.1.0”, “255.255.255.0”);

Ipv4InterfaceContainer interfaces = address.Assign(devices);

// Set up a UDP server

uint16_t port = 9;

UdpServerHelper server(port);

ApplicationContainer serverApps = server.Install(nodes.Get(1));

serverApps.Start(Seconds(1.0));

serverApps.Stop(Seconds(10.0));

// Set up a UDP client

uint32_t packetSize = 1024; // 1 KB

uint32_t maxPacketCount = 100; // 100 KB total data

Time interPacketInterval = Seconds(0.05); // 50 ms interval

UdpClientHelper client(interfaces.GetAddress(1), port);

client.SetAttribute(“MaxPackets”, UintegerValue(maxPacketCount));

client.SetAttribute(“Interval”, TimeValue(interPacketInterval));

client.SetAttribute(“PacketSize”, UintegerValue(packetSize));

ApplicationContainer clientApps = client.Install(nodes.Get(0));

clientApps.Start(Seconds(2.0));

clientApps.Stop(Seconds(10.0));

Simulator::Stop(Seconds(10.0));

Simulator::Run();

// Assume we have vectors of original and received data

std::vector<uint8_t> originalData; // Fill this with the original data

std::vector<uint8_t> receivedData; // Fill this with the received data

// Example data

for (uint32_t i = 0; i < maxPacketCount * packetSize; ++i) {

originalData.push_back(static_cast<uint8_t>(i % 256));

receivedData.push_back(static_cast<uint8_t>((i + 1) % 256)); // Simulating some differences

}

// Calculate PSNR

double psnr = calculatePSNR(originalData, receivedData);

std::cout << “PSNR: ” << psnr << ” dB” << std::endl;

Simulator::Destroy();

return 0;

}

Explanation:

Here, we briefly explain the process for PSNR calculation in ns3:

  1. Simulation Setup:
    • Create two nodes and connect them using a point-to-point link.
    • Install the Internet stack on both nodes and assign IP addresses.
  2. Application Setup:
    • Install a UDP server on the destination node (Node 1).
    • Install a UDP client on the source node (Node 0) to send packets to the server.
  3. Data Collection:
    • Collect original and received data. For the purpose of this example, original and received data are simulated as vectors.
  4. MSE Calculation:
    • calculateMSE function computes the mean squared error between the original and received data.
  5. PSNR Calculation:
    • calculatePSNR function uses the MSE to calculate the PSNR.

Replace the example data with the actual data collected during your ns-3 simulation. The originalData should be the data before transmission, and receivedData should be the data after reception.Finally, we had calculated the PSNR in ns3 has successfully implemented and executed. We also provide and support further information related to PSNR performance in other simulation tools.  If you require assistance with conducting a networking comparison analysis, please reach out to ns3simulation.com for support with calculating PSNR in ns3tool.