Face normalization - Image processing - c++

I have a problem. I found an academic paper for age detection, which tries to predict the age given an image with a face. I've done almost all steps. However, it feels that face normalization doesn't work for me. I searched how to do it, and I don't know why it doesn't look how it should look like.
I don't know what it's missing, some help would be appreciated.
This is my code:
void normalize_face(Mat img) {
int height = img.rows;
int width = img.cols;
int no_px = height * width;
int hist[256] = { 0 };
int min_value = 255;
int max_value = 0;
Mat dst = img.clone();
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
uchar px = img.at<uchar>(i, j); // CV_8UC3 image type, with all channels equal -> grayscale
hist[px]++;
}
}
for (int i = 0; i < 256; i++) {
if (hist[i] != 0 && i < min_value)
min_value = i;
if (hist[i] != 0 && i > max_value)
max_value = i;
}
float constant_factor = 255.0f / (max_value - min_value);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
uchar px = img.at<uchar>(i, j);
float new_px_value = constant_factor * img.at<uchar>(i, j);
dst.at<uchar>(i, j) = (int)new_px_value;
}
}
std::cout << "Minim: " << min_value << ", maxim: " << max_value << "\n";
std::cout << "Constant factor:" << constant_factor<<"\n";
imshow("normalized face", dst);
imshow("normal face", img);
waitKey(0);
}
This is what I get:
And this is what I should get:

Related

I cant iterate through pixels of all the image, it is iterating through parts of it. OpenCV

I have the following code:
void white(Mat&src,Mat&dst){
double h = src.cols;
double w = src.rows;
dst = src.clone();
for (int i = 0; i < dst.rows; i++) {
for (int j = 0; j < dst.cols; j++) {
dst.at<uchar>(i, j) = 255;
}
}
}
My expected result is to get a completely white image, however, I get this result:
Input Image:
Output Image:
It's a color image. Each pixel consists of 3 values. You have to set each color channel
void white(Mat&src,Mat&dst){
double h = src.cols;
double w = src.rows;
dst = src.clone();
for (int i = 0; i < dst.rows; i++) {
for (int j = 0; j < dst.cols; j++) {
for (std::size_t c = 0; c < 3; ++c) {
dst.at<Vec3b>(i, j)[c] = 255;
}
}
}
}

Weird symbols coming out of matrices

I'm trying to print out individual values from the matrices from all images. However, the output that i am receiving are weird symbols and alphabets.
I have 60 images and each of them have a matrix of 320x240.
Sorry, my code may not be good or up to standard as i'm not very good in this.
Thanks :)
vector<Mat> images;
for (int i = 0;i < 60;i++) {
if (i < 10) {
Mat in = imread("ts_04-11-21_16-27-0" + to_string(i) + "-mod.jpg", CV_8UC1);
images.push_back(in);
}
else {
Mat in = imread("ts_04-11-21_16-27-" + to_string(i) + "-mod.jpg", CV_8UC1);
images.push_back(in);
}
}
for (int i = 0; i < 60; i++) {
for (int j = 0; j < 320; j++) {
for (int k = 0; k < 240; k++) {
cout << images[i].at<uint8_t>(j, k) << endl;
}
}
}

How to take pixel coordinates from an image in c++ using specific conditions

I want to get (x,Y) co-ordinates from an image where the pixel value is not zero. I got the following error in this code:
error- bad access:
camera.cpp
void Camera ::write_uint8_image_1(uint8_image_t *image, int *output)
{
int index = 1;
for(uint32_t i = 0; i < image->h; i++)
{
for(uint32_t j = 0; j < image->w; j++)
{
if(image->data[i * image->w + j] != 0)
output[index++] = i;
output[index++] = j; /* error : bad access */
}
}
output[0] = index;
}
main.cpp
int output[800] = {0};
/*print output*/
C1.write_uint8_image_1(c.output_image, output);
for (int i = 1; i < output[0]; i++)
std::cout<< output[i] << " , ";

window operation by Pointer of image

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;
}

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.