Is blockiness expected for textures with format GL_RGBA8 with unsigned byte & min/mag filter GL_NEAREST? - opengl-es-3.0

When format GL_RGB5_A1 is used with unsigned_byte texture data (no mipmap), the applied texture is blocky with min/mag filters GL_NEAREST.
When same code used for format GL_RGBA8, the applied texture is smooth. My assumption was that for RGBA8 too using GL_NEAREST filters the texture image should be blocky as attached.
OPGNELES 3.0 supports this format and type for textures.
Its a 3D texture of size 256x256x256 applied using glTexImage3D and viewport is set for 640x480.
Texture is generated as below
for(k = 0; k < 256; k++) for(j = 0; j < 256; j++) for(i = 0; i < 256; i++)
{
pUBPointer[0] = 255-i;
pUBPointer[1] = 255-j;
pUBPointer[2] = 255-k;
pUBPointer[3] = 0xFF;
pUBPointer += 4;
}
Is it expected?
Image for format RGB5_A1
Image for format RGBA8

Works as intended. nearest takes only one sample from texture from nearest texel. Difference between RGB8 texels (in one direction) is 1/256 - which is visually almost undistunguishable. However, with RGB5, only 5 bits allocated for each colour, so differense is 1/32.

Related

Extract area with no noise

What is the best way to extract the part with pattern from binary images like these? Size and position of pattern may vary a bit from image to image.
I've tried morphologyEx, but it looses too much info (and pattern position/size)
How do detect too noisy images?
Thanks in advance.
UPD
Looks like it works now. Still dont know how to detect 'bad' noisy frames. Here is an example with an excellent frame.
orig img (240x320).
(0)-> Morph close 4x4, to find large black areas.
(0) -> Morph open 2x2 -> Morph close 2x2 -> set black where black in (1).
(2) -> gaussian blur 13x13.
(3) -> gray to bin and leave only white zones with area more than some value.
When all the frames are processed 1-4:
for (var df in dFrames) {
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++) {
if (df.frame[x][y] == 0xffffffff)
screenImg[x][y] += (int)(pow(df.whiteArea, 1.2) / maxWhiteAreaInAllDfs * 100);
}
}
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++) {
if (screenImg[x][y] > dFrames.length * 0.5 * (100/2).floor())
screenImg[x][y] = 0xffffffff;
}
Finally crop all the frames (4), wrap perspective, find pattern width/height and calc avg color in every 'square'.

Kinect depth and color image

I got a little problem with the depth map to point color map,
i simply threshold the nearst depth (about 70-80cm), then i bitwise and the thresholded depth image to corresponding color map,
Mat depthFilter(Mat depth,Mat color){
Mat I;
depth.convertTo(I, CV_8UC1, 255.0 / 4096.0);
unsigned char *input = (unsigned char*)(I.data);
for (int i = 0; i < I.cols; i++){
for (int j = 0; j < I.rows; j++){
int pixel = input[I.cols*j + i];
if (!(pixel <52 && pixel >42)){
input[I.cols*j + i] = 0;
}
else
{
input[I.cols*j + i] = 255;
}
}
}
cvtColor(color, color, CV_BGR2GRAY);
bitwise_and(I, color, I);
return I;
}
(I'm using OpenCvKinect, which uses OpenNi and OpenCv)
But my problem is, the point's are not the same.. I think i need to find some relation between two images, but how :)!
http://postimg.org/image/hyxt25bwd/
I would see Why kinect color and depth won't align correctly? as they are having a similar problem in matlab. The answer suggest to use OpenNI's AlternateViewCapability class to align the images. This is the documentation from the older version of OpenNI (1.5) as I cannot find the 2.0 documentation for C++, but there is probably a similar method. The images on that answer show the difference the shift made.
The code is essentially
depth.GetAlternativeViewPointCap().SetViewPoint(image); //depth is depth generator
//image is color generator
I am not sure if you have already solved the problem of alignment, however this has been implemented within OpenCVKinect Wrappers that you are already using.
To acquire aligned Depth and Color images from Kinect, you need to use setMode function as follows:
setMode(C_MODE_DEPTH | C_MODE_COLOR | C_MODE_ALIGNED);

How to make OpenCV IplImage for 16 bit gray-data?

This code is for 8 bit data to make gray-scale IplImage.
IplImage* img_gray_resize = NULL;
img_gray_resize = cvCreateImage(cvSize(320, 256), IPL_DEPTH_8U, 1);
DWORD dwCount;
LVDS_SetDataMode(0); // o for 8 bit mode and 1 for 16 bit mode
dwCount = (LONG)320 * (LONG)256;
unsigned char* m_pImage = NULL;
m_pImage = new unsigned char[320 * 256];
for (int i=0; i<320 * 256; i++) m_pImage[i] = NULL;
LVDS_GetFrame(&dwCount, m_pImage);
int width = 320;
int height = 256;
int nn = 0;
int ii = 0;
for (int y=0; y<height; y++)
{
for (int x=0; x<width; x++)
{
ii = y * width + x;
if(nn < (height*width))
img_gray_resize->imageData[ii] = m_pImage[nn++];
}
}
delete [] m_pImage;
I need to display 16 bit gray-scale image. If I display 8 bit data, some information is missing from the image. However, LVDS_SetDataMode() can provide both types of data. I am using a library for frame grabber device. Please help me.
16 bit images should be stored in IPL_DEPTH_16U (or CV_16U) mode. This is the correct memory layout.
However, displaying them depends on your display hardware.
Most regular display APIs, e.g. OpenCV's highgui, can only display 8-bit images.
To actually display the image, you will have to convert your image to 8-bits for display.
You will need to decide how to do this. There are many ways to do this, depending on your application and complexity. Some options are:
Show MSB = right-shift the image by 8 pixels.
Show LSB = saturate anything above 255.
In fact, right-shift by any value between 0-8 bits, combined with a cv::saturate_cast to avoid value wrap-around.
HDR->LDR = Apply dynamic range compression algorithms.
as I know,only 8bit data can be displayed,you need to find the best way to convert the 16bit to 8bit to minimize the information you lose. Histogram equalization can be applyed to do this.
Finally, I have solved the problem by following way:
dwCount = (LONG)320 * (LONG)256 * 2;
LVDS_SetDataMode(1);
img_gray_resize->imageData[ii] = m_pImage[nn++] >> 6;
Just shift bits to right (2, 3, 4, 5, 6, ...), where you get good result, use that value.

Replicate OpenCV resize with bilinar interpolation in C (shrink only)

I'm trying to make a copy of the resizing algorithm of OpenCV with bilinear interpolation in C. What I want to achieve is that the resulting image is exactly the same (pixel value) to that produced by OpenCV. I am particularly interested in shrinking and not in the magnification, and I'm interested to use it on single channel Grayscale images. On the net I read that the bilinear interpolation algorithm is different between shrinkings and enlargements, but I did not find formulas for shrinking-implementations, so it is likely that the code I wrote is totally wrong. What I wrote comes from my knowledge of interpolation acquired in a university course in Computer Graphics and OpenGL. The result of the algorithm that I wrote are images visually identical to those produced by OpenCV but whose pixel values are not perfectly identical (in particular near edges). Can you show me the shrinking algorithm with bilinear interpolation and a possible implementation?
Note: The code attached is as a one-dimensional filter which must be applied first horizontally and then vertically (i.e. with transposed matrix).
Mat rescale(Mat src, float ratio){
float width = src.cols * ratio; //resized width
int i_width = cvRound(width);
float step = (float)src.cols / (float)i_width; //size of new pixels mapped over old image
float center = step / 2; //V1 - center position of new pixel
//float center = step / src.cols; //V2 - other possible center position of new pixel
//float center = 0.099f; //V3 - Lena 512x512 lower difference possible to OpenCV
Mat dst(src.rows, i_width, CV_8UC1);
//cycle through all rows
for(int j = 0; j < src.rows; j++){
//in each row compute new pixels
for(int i = 0; i < i_width; i++){
float pos = (i*step) + center; //position of (the center of) new pixel in old map coordinates
int pred = floor(pos); //predecessor pixel in the original image
int succ = ceil(pos); //successor pixel in the original image
float d_pred = pos - pred; //pred and succ distances from the center of new pixel
float d_succ = succ - pos;
int val_pred = src.at<uchar>(j, pred); //pred and succ values
int val_succ = src.at<uchar>(j, succ);
float val = (val_pred * d_succ) + (val_succ * d_pred); //inverting d_succ and d_pred, supposing "d_succ = 1 - d_pred"...
int i_val = cvRound(val);
if(i_val == 0) //if pos is a perfect int "x.0000", pred and succ are the same pixel
i_val = val_pred;
dst.at<uchar>(j, i) = i_val;
}
}
return dst;
}
Bilinear interpolation is not separable in the sense that you can resize vertically and the resize again vertically. See example here.
You can see OpenCV's resize code here.

Average blurring mask produces different results

multiplying each pixel by the average blurring mask *(1/9) but the result is totally different.
PImage toAverageBlur(PImage a)
{
PImage aBlur = new PImage(a.width, a.height);
aBlur.loadPixels();
for(int i = 0; i < a.width; i++)
{
for(int j = 0; j < a.height; j++)
{
int pixelPosition = i*a.width + j;
int aPixel = ((a.pixels[pixelPosition] /9));
aBlur.pixels[pixelPosition] = color(aPixel);
}
}
aBlur.updatePixels();
return aBlur;
}
Currently, you are not applying an average filter, you are only scaling the image by a factor of 1/9, which would make it darker. Your terminology is good, you are trying to apply a 3x3 moving average (or neighbourhood average), also known as a boxcar filter.
For each pixel i,j, you need to take the sum of (i-1,j-1), (i-1,j), (i-1,j+1), (i,j-1), (i,j),(i,j+1),(i+1,j-1),(i+1,j),(i+1,j+1), then divide by 9 (for a 3x3 average). For this to work, you need to not consider the pixels on the image edge, which do not have 9 neighbours (so you start at pixel (1,1), for example). The output image will be a pixel smaller on each side. Alternatively, you can mirror values out to add an extra line to your input image which will make the output image the same size as the original.
There are more efficient ways of doing this, for example using FFT based convolution; these methods are faster because they don't require looping.

Resources