window operation by Pointer of image - c++

If we access pixel by a pointer using step and data of Mat Image. see example below
int step = srcimg.step;
for (int j = 0; j < srcimg.rows; j++) {
for (int i = 0; i < srcimg.cols; i++) {
//this is pointer to the pixel value.
uchar* ptr = srcimg.data + step* j + i;
}
}
Question:
How can we perform 3x3 weighted avg operations with image step by a pointer?
thanks

You mustn't use data field in opencv because memory is not allways continuous. you can check this using isContinuous() method.
Now you can do like this (image type is CV_8UC1)
for (int i = 1; i < srcimg.rows-1; i++)
{
for (int j = 1; j < srcimg.cols-1; j++)
{
int x=0;
for (int k=-1;k<=1;k++)
{
uchar* ptr=srcimg.ptr(k+i)+j-1;
for (int l=-1;l<=1;l++,ptr++)
x +=*ptr;
}
}
}
image border are not processed. Now if you want to blur an image use blur method
You can use this post too

I am doing something like this .
int sr = 3;
for (int j = 0; j < srcimg.rows; j++) {
for (int i = 0; i < srcimg.cols; i++) {
uchar* cp_imptr = im.data;
uchar* tptr = im.data + imstep *(sr + j) + (sr + i);
int val_tptr = cp_imptr [imstep *(sr + j) + (sr + i)]; //pointer of image data amd step at 3x3
int val_cp_imptr = cp_imptr[imstep *j + i];
double s = 0;
for (int n = templeteWindowSize; n--;)
{
for (int m = templeteWindowSize; m--;)
{
uchar* t = tptr; //pointer of template
// sum
s += *t;
t++;
}
t += cstep;
}
}
cout << endl;
}

Related

How do I change the values in a 2d array using 1d array?

I want to make the values of num[] replace all of the a[][] values when one of the numbers equal k. So all the values of num correspond to each place at k. So for example when k reaches 20 if there is a 20 in the 2d array I want to replace all 20's with whatever is in num[19], but whenever I try it that, they all become skewed numbers and I can't find the reason why. Are my for loops set up wrong or what else could be the problem?
#include<iostream>
int main(){
//other code that uses a file to make 2d array
int width, height, maxval;
fin >> P2 >> width >> height >> maxval;
int **a = new int *[height];
for (int i = 0; i < height; i++)
a[i] = new int[width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
fin >> a[i][j];
}
}
}
void eq(int **a, int h, int w) {
int num[255];
double num1[255];
double prob[255], cumul[255]{ 0 };
double x, y, z=0;
for (int k = 1; k <= 255; k++)
{
int temp = 0;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {//counts the repeated pixel values
if (pix[i][j] == k)
{
temp += 1;
}
}
}
num1[k - 1] = temp;
}
for (int i = 0; i < 255; i++) {
prob[i] = (num1[i] / (height*width));//show the decimal number of how many pixel values are in the image over the total
cout << prob[i] << endl;
}
for (int i = 0; i < 255; i++) {
y = prob[i];
x = y + z;
z = x;// adds all the probabilities to make the sum
cumul[i] =x;
cout << cumul[i] << endl;
}
for (int i = 0; i < 255; i++) {
num[i] =floor(cumul[i]*255);// converts the cumulative number to the new pixel value and sets it in a array
}
for (int k = 1; k <= 255; k++) {//loop that is not coming out right
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
if (a[i][j] == k)
{
a[i][j] =num[k-1];
}
}
}
}
}
Basically I am making a function that deals with histogram equalization to make a pgm image clearer. In the main function I am calling a pgm file and setting all the pixel values into a 2d array. So the num[] is the part where I make the new pixel values, but for some reason whenever I call for example a[0][0] I should be getting something that is not zero or 255 since both of those values mean that none of the pixels had that corresponding intensity, but whenever I call it I get 255 or some other random number.
If i understand what you want to do, this line :
a[i][j] =num[i];
should be :
a[i][j] =num[k-1];
Because you want:
if( a[i][j] = k = 20){
a[i][j] = num[k-1 = 19]
}

Comparing pixels in alpha-trimmed filter

I have the following problem. I have written code for alpha-trimmed filter in opencv library. I think that it is properly constructed but I don't know how to compare two 3 channels pixels during sorting a 'window with pixels'. In my code it is done but comparing two but it is impossible for vectors. I assume that i should compare it one channel and after second and so on. Have you any hints for me, or could you propose some modifications in my code. This is my code.
int alphatrimmed(Mat img, int alpha)
{
Mat img9 = img.clone();
const int start = alpha;
const int end = 9 - alpha;
//going through whole image
for (int i = 1; i < img.rows - 1; i++)
for (int j = 1; j < img.cols-1; j++)
{
int k = 0;
Vec3b element[9];
//selecting elements
for (int m = i - 1; m < i + 2; m++)
for (int n = j - 1; n < j + 2; n++)
element[k++] = img.at<Vec3b>(m*img.cols + n);
for (int i = 0; i < end; i++)
{
int min = i;
for (int j = i + 1; j < 9; j++)
if (element[j] < element[min])
min = j;
Vec3b temp = element[i];
element[i] = element[min];
element[min] = temp;
}
const int result = (i - 1)*(img.cols - 2) + j - 1;
img9.at<Vec3b>(result) = element[start];
for (int j = start + 1; j < end; j++)
img9.at<Vec3b>(result) += element[j];
img9.at<Vec3b>(result) /= 9 - alpha;
}
namedWindow("AlphaTrimmed Filter", WINDOW_AUTOSIZE);
imshow("AlphaTrimmed Filter", img9);
return 0;
}
Thank you for your time spent on solving my problem.

How to find unique labels for segments in SuperpixelSLIC

I am using cv::ximgproc::SuperpixelSLIC opencv c++ to generate segments of image. I want each segment label to be unique. Here is my code.
Mat segmentImage() {
int num_iterations = 4;
int prior = 2;
bool double_step = false;
int num_levels = 10;
int num_histogram_bins = 5;
int width, height;
width = h1.size().width;
height = h1.size().height;
seeds = createSuperpixelSLIC(h1);
Mat mask;
seeds->iterate(num_iterations);
Mat labels;
seeds->getLabels(labels);
for (int i = 0; i < labels.rows; i++) {
for (int j = 0; j < labels.cols; j++) {
if (labels.at<int>(i, j) == 0)
cout << i << " " << j << " " << labels.at<int>(i, j) << endl;
}
}
ofstream myfile;
myfile.open("label.txt");
myfile << labels;
myfile.close();
seeds->getLabelContourMask(mask, false);
h1.setTo(Scalar(0, 0, 255), mask);
imshow("result", h1);
imwrite("result.png", h1);
return labels;
}
In label.txt file I observe that label 0 has been given to two segments (i.e. segment include pixel(0,0) and pixel(692,442). These two segments are pretty far away.
Is this normal thing or my code is incorrect. Please help me to find unique label for each segment.
What you essentially need is a connected components algorithm. Without knowing the exact SLIC implementation you use, SLIC usually tends to produce disconnected superpixels, i.e. disconnected segments with the same label. A simple solution I used is the connected components algorithm form here: https://github.com/davidstutz/matlab-multi-label-connected-components (originally from here: http://xenia.media.mit.edu/~rahimi/connected/). Note that this repository contains a MatLab wrapper. In your case you only need connected_components.h together with the following code:
#include "connected_components.h"
// ...
void relabelSuperpixels(cv::Mat &labels) {
int max_label = 0;
for (int i = 0; i < labels.rows; i++) {
for (int j = 0; j < labels.cols; j++) {
if (labels.at<int>(i, j) > max_label) {
max_label = labels.at<int>(i, j);
}
}
}
int current_label = 0;
std::vector<int> label_correspondence(max_label + 1, -1);
for (int i = 0; i < labels.rows; i++) {
for (int j = 0; j < labels.cols; j++) {
int label = labels.at<int>(i, j);
if (label_correspondence[label] < 0) {
label_correspondence[label] = current_label++;
}
labels.at<int>(i, j) = label_correspondence[label];
}
}
}
int relabelConnectedSuperpixels(cv::Mat &labels) {
relabelSuperpixels(labels);
int max = 0;
for (int i = 0; i < labels.rows; ++i) {
for (int j = 0; j < labels.cols; ++j) {
if (labels.at<int>(i, j) > max) {
max = labels.at<int>(i, j);
}
}
}
ConnectedComponents cc(2*max);
cv::Mat components(labels.rows, labels.cols, CV_32SC1, cv::Scalar(0));
int component_count = cc.connected<int, int, std::equal_to<int>, bool>((int*) labels.data, (int*) components.data, labels.cols,
labels.rows, std::equal_to<int>(), false);
for (int i = 0; i < labels.rows; i++) {
for (int j = 0; j < labels.cols; j++) {
labels.at<int>(i, j) = components.at<int>(i, j);
}
}
// component_count would be the NEXT label index, max is the current highest!
return component_count - max - 1;
}
On the obtained labels, run relabelConnectedSuperpixels.

Using BOOST::UBLAS and FFTW together for image processing

Is there a possibility to use a boost matrix along FFTW? if so how do you do it?
what i basically have is
QPixmap pixmap("lena.bmp");
// resize input image
pixmap = pixmap.copy(512,512,128,128);
pixmap = pixmap.scaled(128,128);
QImage image = pixmap.toImage();
QRgb col;
int g;
int width = pixmap.width();
int height = pixmap.height();
matrix<double> m(width,height);
for (int j = 0; j < m.size2(); j++)
{
for (int i = 0; i < m.size1(); i++)
{
m(i,j) = 0;
m(i,j) = qGray(image.pixel(i,j));
}
}
I want to perform FFTW on the matrix 'm' and then redisplay the fft of the image. how do i do this?
you can do is first read your image into an array, then apply the FFTW as per your needs on this array and then fill this array into a boost ublas matrix and then use it.
int a[width][height];
for (int j = 0; j < width; j++)
{
for (int i = 0; i < height; i++)
{
a[i][j] = qGray(image.pixel(i,j));
}
}
//apply fftw
matrix<double> m(width,height);
for (int j = 0; j < width; j++)
{
for (int i = 0; i < height; i++)
{
m(i,j) = fft_a[i][j];
}
}
I hope this works

Printing to a STL(stereolithography) file in binary mode

I am trying to print to a stl file and can't print correctly.
There are lot of samples for Hex format printing in C++ but no sample program for binary format. My program is as follow. What is wrong with my program?
string name = "Create by stlwrite.m ";
name = name + currentDateTime();
pFile.setf(ios::left);
pFile.width(sizeof(unsigned char)*80);
//header
pFile << name;
unsigned int size = faces.rows;
//size
pFile.write((char*)&size,sizeof(size));
int height = 25;
unsigned short ** data= new unsigned short *[height];
for(int i = 0; i < height; i++)
{
data[i] = new unsigned short[142000];
}
for(int j = 0; j < 142000; j++)
{
int i = 0;
//for one facets
for(int k = 0; k < (*facets[j]).cols; k++)
{
for(int l = 0; l < (*facets[j]).rows; l++)
{
float f = (*facets[j]).at<float>(l,k);
data[i][j] = *reinterpret_cast<unsigned int *>(&f);
data[i+1][j] = *reinterpret_cast<unsigned int *>(&f)>>16;
i = i + 2;
}
}
//then for the last row
data[height-1][j] = (unsigned short)0;
}
for (int i = 0; i < height; i++)
for (int j = 0; j < faces.rows; j++)
pFile.write ((char*)&data[i][j], sizeof(unsigned short) );
pFile.close();
EDIT1: I follow the idea of Matlab stlwrite.mat program.link
This is the C code to print in binary mode.
The calling function is:
stl_write_binary(X, Y, path)
Where X is 3xM Vertices matrix and Y is 3xN faces matrix. Both are in OpenCV's Mat structure.
Path is the path to store the STL file you can modify it according to your requirement.
The whole code is:
int stl_write_binary(Mat &vertemp, Mat &faces, PathToFolders &path)
{
Mat vertices(vertemp.cols,vertemp.rows,vertemp.type());
vertices = vertemp.t();
cv::Mat** facets = new cv::Mat*[faces.rows];
for(int i = 0; i < faces.rows; i++)
{
facets[i] = new cv::Mat(3,4,CV_32F);
for(int j = 0; j < 3; j++)
{
vertices(Range::all(),Range(faces.at<int>(i,j),faces.at<int>(i,j)+1)).convertTo((*(facets[i]))(Range::all(),Range(j+1,j+2)), CV_32F);
}
}
//Compute their normals
Mat V1(3,faces.rows,CV_32F);
Mat V2(3,faces.rows,CV_32F);
for(int i = 0; i < faces.rows; i++)
{
V1(Range::all(),Range(i,i+1)) = ((*(facets[i]))(Range::all(),Range(2,3))) - ((*(facets[i]))(Range::all(),Range(1,2)));
V2(Range::all(),Range(i,i+1)) = ((*(facets[i]))(Range::all(),Range(3,4))) - ((*(facets[i]))(Range::all(),Range(1,2)));
}
Mat V3(3,faces.rows,CV_32F);
Mat V4(3,faces.rows,CV_32F);
Mat V5(3,faces.rows,CV_32F);
Mat V6(3,faces.rows,CV_32F);
V1(Range(1,2),Range::all()).copyTo(V3(Range(0,1),Range::all()));
V1(Range(2,3),Range::all()).copyTo(V3(Range(1,2),Range::all()));
V1(Range(0,1),Range::all()).copyTo(V3(Range(2,3),Range::all()));
V2(Range(2,3),Range::all()).copyTo(V4(Range(0,1),Range::all()));
V2(Range(0,1),Range::all()).copyTo(V4(Range(1,2),Range::all()));
V2(Range(1,2),Range::all()).copyTo(V4(Range(2,3),Range::all()));
V2(Range(1,2),Range::all()).copyTo(V5(Range(0,1),Range::all()));
V2(Range(2,3),Range::all()).copyTo(V5(Range(1,2),Range::all()));
V2(Range(0,1),Range::all()).copyTo(V5(Range(2,3),Range::all()));
V1(Range(2,3),Range::all()).copyTo(V6(Range(0,1),Range::all()));
V1(Range(0,1),Range::all()).copyTo(V6(Range(1,2),Range::all()));
V1(Range(1,2),Range::all()).copyTo(V6(Range(2,3),Range::all()));
Mat normals(3,faces.rows,CV_32F);
normals = V3.mul(V4) - V5.mul(V6);
V1.release();
V2.release();
V3.release();
V4.release();
V5.release();
V6.release();
Mat normalsqu(3,faces.rows,CV_32F);
Mat normalsqu_colm_summed(1,faces.rows,CV_32F);
normalsqu = normals.mul(normals);
cv::reduce(normalsqu, normalsqu_colm_summed, 0, CV_REDUCE_SUM, CV_32F);
cv::sqrt(normalsqu_colm_summed,normalsqu_colm_summed);//check mem leak
normalsqu.release();
normalsqu_colm_summed = 1/normalsqu_colm_summed;
for(int i = 0; i < faces.rows; i++)
{
normals(Range::all(),Range(i,i+1)) = normals(Range::all(),Range(i,i+1)) * normalsqu_colm_summed.at<float>(i);
}
normalsqu_colm_summed.release();
for(int i = 0; i < faces.rows; i++)
{
normals(Range::all(),Range(i,i+1)).copyTo(((*(facets[i]))(Range::all(),Range(0,1))));
}
normals.release();
//write to stl file
//get file paths
std::vector<std::string> masktoken;
split(path.pathtoimages, '/', masktoken);
path.pathtoSTL = path.pathtoSTL+masktoken[0];
for(int i = 1; i < masktoken.size()-1; i++)
{
path.pathtoSTL = path.pathtoSTL+"/"+masktoken[i];
}
path.pathtoSTL = path.pathtoSTL+"/"+"mesh.stl";
cout<<"Saving file to "<<path.pathtoSTL<<endl;
const char * c = path.pathtoSTL.c_str();
ofstream pFile;
pFile.open (c, ios::out | ios::binary);
if (pFile.is_open())
{
string name = "Create by stlwrite.m ";
name = name + currentDateTime();
pFile.setf(ios::left);
pFile.width(sizeof(unsigned char)*80);
//header
pFile << name;
unsigned int size = faces.rows;
//size
pFile.write((char*)&size,sizeof(size));
int height = (*facets[0]).rows * (*facets[0]).cols * 2 + 1;
unsigned short ** data= new unsigned short *[height];
for(int i = 0; i < height; i++)
{
data[i] = new unsigned short[faces.rows];
}
for(int j = 0; j < faces.rows; j++)
{
int i = 0;
//for one facets
for(int k = 0; k < (*facets[j]).cols; k++)
{
for(int l = 0; l < (*facets[j]).rows; l++)
{
float f = (*facets[j]).at<float>(l,k);
data[i][j] = *reinterpret_cast<unsigned int *>(&f);
data[i+1][j] = *reinterpret_cast<unsigned int *>(&f)>>16;
i = i + 2;
}
}
//then for the last row
data[height-1][j] = (unsigned short)0;
}
for (int i = 0; i < faces.rows; i++)
for (int j = 0; j < height; j++)
pFile.write ((char*)&data[j][i], sizeof(unsigned short) );
pFile.close();
//fclose (pFile);
//delete table
for(int i = 0; i < height; i++)
{
delete[] data[i];
}
delete[] data;
}else{
cout<<"stlwrite:cannotWriteFile"<<" "<<"Unable to write to"<<" "<<path.pathtoSTL<<endl;
}
for(int i = 0; i < faces.rows; i++)
{
(*facets[i]).release();
}
delete[] facets;
return 1;
}