For https://gist.github.com/promach/9d185d35a6e6db0da10992a19c36f754#file-host-cpp-L172 or line 172 of the following coding , why am I getting rgb_stream[STREAM_WIDTH] equals to 192, while all other entries of the array are equal to zero ?
// g++ -g host.cpp -o host `pkg-config --cflags --libs opencv`
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#include <fstream> // std::ifstream, std::ofstream
#include <string>
#include <sys/wait.h>
#include <errno.h>
#include <cmath>
using namespace cv;
using namespace std;
#define LOOPBACK 1
//#define RGB2YUV 1
unsigned int image_width;
unsigned int image_height;
const unsigned int CHNL_NUM = 3;
const unsigned int RED_CHNL = 0;
const unsigned int GREEN_CHNL = 1;
const unsigned int BLUE_CHNL = 2;
const unsigned int STREAM_WIDTH = 128;
const unsigned int NUM_OF_BITS_PER_BYTE = 8;
const unsigned int PIXEL_VALUE_RANGE = 8; // number of bits occupied by [R, G, B] or [Y, U, V] respectively (8-bit unsigned integer for each components) , https://docs.microsoft.com/en-us/windows-hardware/drivers/display/yuv-rgb-data-range-conversions
const unsigned int NUM_OF_COMPONENTS_IN_A_PIXEL = 3; // input: [R, G, B] output:[Y, U, V]
const unsigned int PIXEL_NUM_THAT_FITS_STREAM_WIDTH = 5; // 128-bit stream can at most fits 5 pixels ((PIXEL_NUM_THAT_FITS_STREAM_WIDTH*NUM_OF_COMPONENTS_IN_A_PIXEL*PIXEL_VALUE_RANGE) bits = 120 bits), each pixels contains R, G, B which are encoded in 8 bits for each of the three color components
struct RGB_packet{
uint8_t R,G,B;
};
struct YUV_packet{
uint8_t Y,U,V;
};
struct YUV_packet* rgb2yuv(struct RGB_packet rgb_input) // convert rgb to yuv
{
uint8_t red = rgb_input.R;
uint8_t green = rgb_input.G;
uint8_t blue = rgb_input.B;
struct YUV_packet *yuv_result;
uint8_t Y = yuv_result->Y;
uint8_t U = yuv_result->U;
uint8_t V = yuv_result->V;
// https://www.pcmag.com/encyclopedia/term/55166/yuv-rgb-conversion-formulas
Y = (uint8_t)(0.299*red + 0.587*green + 0.114*blue);
U = (uint8_t)(0.492*(blue-Y));
V = (uint8_t)(0.877*(red-Y));
return yuv_result;
}
int main(int argc, char *argv[]) {
int fdr, fdw, rd, wr, donebytes;
uint8_t *to_buf, *from_buf, *wr_buf, *rd_buf;
pid_t pid;
struct RGB_packet *tologic;
struct YUV_packet *fromlogic;
fdr = open("/dev/stdout", O_RDONLY); // will change to /dev/xillybus_read_128
fdw = open("/dev/stdin", O_WRONLY); // will change to /dev/xillybus_write_128
if ((fdr < 0) || (fdw < 0)) {
perror("Failed to open Xillybus device file(s)");
exit(1);
}
// READ in an image file
String imageName( "lena512color.tiff" ); // by default
if( argc > 1)
{
imageName = argv[1];
}
Mat image;
image = imread( imageName, IMREAD_COLOR ); // Read the file
if( image.empty() ) // Check for invalid input
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
else
{
image_width = image.size().width;
image_height = image.size().height;
}
namedWindow( "Original Image", CV_WINDOW_AUTOSIZE );
imshow( "Original Image", image );
Mat rgbchannel[CHNL_NUM];
// The actual splitting.
split(image, rgbchannel);
namedWindow("Blue",CV_WINDOW_AUTOSIZE);
imshow("Red", rgbchannel[RED_CHNL]);
namedWindow("Green",CV_WINDOW_AUTOSIZE);
imshow("Green", rgbchannel[GREEN_CHNL]);
namedWindow("Red",CV_WINDOW_AUTOSIZE);
imshow("Blue", rgbchannel[BLUE_CHNL]);
waitKey(0); // see all three split channels before feeding in the channel data to xillybus/RIFFA for hardware computation
pid = fork();
if (pid < 0) {
perror("Failed to fork()");
exit(1);
}
if (pid) {
close(fdr);
vector<RGB_packet> vTo(sizeof(struct RGB_packet) * image_width * image_height); // lena.tiff is sized as 512*512*3
tologic = vTo.data();
if (!tologic) {
fprintf(stderr, "Failed to allocate memory\n");
exit(1);
}
tologic->R = *(rgbchannel[RED_CHNL].data);
tologic->G = *(rgbchannel[GREEN_CHNL].data);
tologic->B = *(rgbchannel[BLUE_CHNL].data);
to_buf = (uint8_t *) tologic;
donebytes = 0;
unsigned int if_index = 0;
while (donebytes < sizeof(struct RGB_packet) * image_width * image_height)
{
if(((sizeof(struct RGB_packet) * image_width * image_height)-donebytes) >= (STREAM_WIDTH/NUM_OF_BITS_PER_BYTE))
{
// arrange the five pixels in the format as in https://i.imgur.com/mdJwk7J.png
if_index++; printf("if_index = %d\n\r", if_index);
uint8_t rgb_stream[STREAM_WIDTH+1]; // contains 5 pixels
rgb_stream[STREAM_WIDTH+1] = '\0';
rgb_stream[0] = 0; // remember that the top 8 bits of the 128-bits stream are ignored
for(unsigned int k=1; (k+NUM_OF_COMPONENTS_IN_A_PIXEL-1)<=STREAM_WIDTH; k=k+NUM_OF_COMPONENTS_IN_A_PIXEL)
{
rgb_stream[k] = tologic[k+donebytes].R;
rgb_stream[k+1] = tologic[k+donebytes].G;
rgb_stream[k+NUM_OF_COMPONENTS_IN_A_PIXEL-1] = tologic[k+donebytes].B;
}
for(unsigned int j=0; j<=STREAM_WIDTH; j++)
{
printf("rgb_stream[%d] = %d\n\r", j, rgb_stream[j]);
}
wr_buf = rgb_stream;
wr = write(fdw, wr_buf, STREAM_WIDTH/NUM_OF_BITS_PER_BYTE);
}
else // the remaining pixels do not fill all five pixel slots for a 128-bit stream
{
//wr_buf = ;
wr = write(fdw, wr_buf, sizeof(struct RGB_packet) * image_width * image_height - donebytes);
}
if ((wr < 0) && (errno == EINTR))
continue;
if (wr <= 0) {
perror("write() failed");
exit(1);
}
donebytes += wr;
}
sleep(1); // Let debug output drain (if used)
close(fdw);
return 0;
}
else {
close(fdw);
vector<YUV_packet> vFrom(sizeof(struct YUV_packet) * image_width * image_height);
fromlogic = vFrom.data();
if (!fromlogic) {
fprintf(stderr, "Failed to allocate memory\n");
exit(1);
}
from_buf = (uint8_t *) fromlogic;
donebytes = 0;
while (donebytes < sizeof(struct YUV_packet) * image_width * image_height) {
if(((sizeof(struct RGB_packet) * image_width * image_height)-donebytes) >= PIXEL_NUM_THAT_FITS_STREAM_WIDTH)
{
rd = read(fdr, from_buf + donebytes, STREAM_WIDTH/NUM_OF_BITS_PER_BYTE);
}
else // the remaining pixels do not fill all five pixel slots for a 128-bit stream
{
rd = read(fdr, from_buf + donebytes, sizeof(struct YUV_packet) * image_width * image_height - donebytes);
}
if ((rd < 0) && (errno == EINTR))
continue;
if (rd < 0) {
perror("read() failed");
exit(1);
}
if (rd == 0) {
fprintf(stderr, "Reached read EOF!? Should never happen.\n");
exit(0);
}
donebytes += rd;
}
for (unsigned int i = 0; i < (image_width * image_height); i++) // check the perfomance of hardware with respect to software computation
{
#ifdef LOOPBACK
if( (tologic[i].R == fromlogic[i].Y) ||
(tologic[i].G == fromlogic[i].U) ||
(tologic[i].B == fromlogic[i].V) )
#elif RGB2YUV
if( (abs(rgb2yuv(tologic[i])->Y - fromlogic[i].Y) > 1) ||
(abs(rgb2yuv(tologic[i])->U - fromlogic[i].U) > 1) ||
(abs(rgb2yuv(tologic[i])->V - fromlogic[i].V) > 1) ) // rgb2yuv conversion hardware tolerance fails by more than 1 compared to software computation
#endif
{
printf("R:%d G:%d B:%d \n", tologic[i].R, tologic[i].G, tologic[i].B);
printf("Y:%d U:%d V:%d \n", fromlogic[i].Y, fromlogic[i].U, fromlogic[i].V);
}
}
sleep(1); // Let debug output drain (if used)
close(fdr);
return 0;
}
}