Digital Image Processing Contrast Stretching Histogram - image

Here I attach my code that I use to Draw the Histogram of the Contrasted image and also to convert a gray image into Contrast Image. Here I used low pint as 122 and highest point as 244. In the output histogram it reduce the height of the histogram.
I cannot find the error in my code
#include "opencv2/opencv.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
using namespace cv;
using namespace std;
int main(int argc, char* argv[]) {
Mat img = imread(argv[1], 1);
if (!img.data) {
cout << "Could not find the image!" << endl;
return -1;
}
int height = img.rows;
int width = img.cols;
int widthstep = img.step;
int ch = img.channels();
printf("Height : %d\n", height);
printf("Width : %d\n", width);
printf("Widthstep : %d\n", widthstep);
printf("No of channels : %d\n", ch);
Mat gray_image(height, width, CV_8UC1, Scalar(0));
cvtColor(img, gray_image, COLOR_BGR2GRAY);
Mat new_image = gray_image.clone();
int v;
int output{};
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int v = (int)gray_image.at<uchar>(y, x);
if (v >= 0 && v <= 122) {
output = int((6 / 122) * v);
}
else if (v > 100 && v <= 244) {
output = int(((244) / (122)) * (v - 122) + 6);
}
else if (v > 244 && v <= 255) {
output = int(((5) / (11)) * (v - 244) + 250);
}
new_image.at<uchar>(y, x) = (uchar)output;
}
}
int histn[256];
for (int i = 0; i < 256; i++) {
histn[i] = 0;
}
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
histn[(int)new_image.at<uchar>(y, x)] = histn[(int)new_image.at<uchar>(y, x)] + 1;
}
}
for (int i = 0; i < 256; i++) {
cout << i << ":" << histn[i] << endl;
}
int hist_wn = 512;
int hist_hn = 400;
int bin_wn = cvRound((double)hist_wn / 256);
Mat new_histogramImage(hist_hn, hist_wn, CV_8UC1, Scalar(255));
int maxn = histn[0];
for (int i = 0; i < 256; i++) {
if (maxn < histn[i]) {
maxn = histn[i];
}
}
for (int i = 0; i < 256; i++) {
histn[i] = ((double)histn[i] / maxn) * new_histogramImage.rows;
}
for (int i = 0; i < 256; i++) {
line(new_histogramImage, Point(bin_wn * (i), hist_hn), Point(bin_wn * (i), hist_hn - histn[i]), Scalar(0), 1, 8, 0);
}
imwrite("Gray_Image.png", gray_image);
imwrite("newcontrast_Image.png", new_image);
imwrite("Histogram.png", new_histogramImage);
namedWindow("Image");
imshow("Image", img);
namedWindow("Gray_Image");
imshow("Gray_Image", gray_image);
namedWindow("newcontrast_Image");
imshow("newcontrast_Image", new_image);
namedWindow("New_Histogram");
imshow("New_Histogram", new_histogramImage);
namedWindow("Old_Histogram");
imshow("Old_Histogram", histImage);
waitKey(0);
return 0;
}
Here are the new and old histograms that I got as outputs

I found the solution for the question. Here I changed the lowest and highest point values as 100 and 240 and when using the values set those as decimals values.
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int v = (int)gray_image.at<uchar>(y, x);
if (v >= 0 && v <= 100) {
output = int((5.0/ 100.0) * v);
}
else if (v > 100 && v <= 240) {
output = int(((245.0) / (140.0)) * (v - 100.0) + 5.0);
}
else if (v > 240 && v <= 255) {
output = int(((5.0) / (15.0)) * (v - 240.0) + 250.0);
}
new_image.at<uchar>(y, x) = (uchar)output;
}
}

Related

Access violation writing location 0x00000000 in middle of a for loop

I'm trying to use mnist dataset for neural networks but im getting a Access violation writing location 0x00000000
the code is
for (int i = 0; i < length; i++) {
innerarray = (int8_t*)malloc(width * height);
for (int j = 0; j < width * height; j++) {
int8_t value = 0;
innerarray[j] = value;
}
temparray[i] = innerarray;
}
for (int i = 0; i < length; i++) {
for (int j = 0; j < width * height; j++) {
int8_t grayscale;
rf.read((char*)&grayscale, 1);
temparray[i][j] = grayscale; //error happens here
}
}
variable values:
int length = 10000;
int width = 28;
int height = 28;
The weird thing is it only happen when i >= 2512. Also replacing grayscale with 0 doesn't work. I can hower set temparray[2512][0] to 0 before the last nested for loop.
Like this:
for (int i = 0; i < length; i++) {
innerarray = (int8_t*)malloc(width * height);
for (int j = 0; j < width * height; j++) {
int8_t value = 0;
innerarray[j] = value;
}
temparray[i] = innerarray;
}
temparray[2512][0] = 0; //works
for (int i = 0; i < length; i++) {
for (int j = 0; j < width * height; j++) {
int8_t grayscale;
rf.read((char*)&grayscale, 1);
temparray[i][j] = 0; //error still happens here
}
}
The full code is:
#include<iostream>
#include<fstream>
#include<cstdint>
#include<cstdlib>
#include<array>
using namespace std;
struct images {
int32_t height = 0;
int32_t width = 0;
int32_t magicnumber = 0;
int32_t numberofimages = 0;
int8_t** images[];
void setimages(int8_t** newimages) {
delete[] this->images;
int8_t** images = (int8_t**)malloc(numberofimages);
int8_t* innerarray;
for (int i = 0; i < numberofimages; i++) {
innerarray = (int8_t*)malloc(width * height);
images[i] = innerarray;
}
for (int i = 0; i < numberofimages; i++) {
for (int j = 0; j < width * height; j++) {
images[i][j] = newimages[i][j];
}
}
};
};
struct labels {
int32_t magicnumber = 0;
int32_t numberoflabels = 0;
int8_t labels[];
};
int32_t litleendiantobig(int32_t litle) {//reverse works as well
int32_t big = ((4278190080 & litle) >> 24) + ((255 & litle) << 24) + ((16711680 & litle) >> 8) + ((65280 & litle) << 8);
return big;
}
images loadimages(string filename, int32_t magicalnumber) {
ifstream rf(filename, ios::out | ios::binary);
if (!rf) {
cout << "Cannot open file! " << filename << endl;
exit(1);
}
int32_t magicnumberoffile;
rf.read((char*)&magicnumberoffile, 4);
magicnumberoffile = litleendiantobig(magicnumberoffile);
if (magicalnumber != magicnumberoffile) {
cout << "Wrong magic number!" << endl;
cout << "expected:" << magicalnumber << endl;
cout << "got:" << magicnumberoffile << endl;
exit(1);
}
images img;
int32_t length;
rf.read((char*)&length, 4);
length = litleendiantobig(length);
img.numberofimages = length;
int32_t width;
rf.read((char*)&width, 4);
width = litleendiantobig(width);
img.width = width;
int32_t height;
rf.read((char*)&height, 4);
height = litleendiantobig(height);
img.height = height;
int8_t** temparray = (int8_t**)malloc(length);
int8_t* innerarray;
for (int i = 0; i < length; i++) {
innerarray = (int8_t*)malloc(width * height);
for (int j = 0; j < width * height; j++) {
int8_t value = 0;
innerarray[j] = value;
}
temparray[i] = innerarray;
}
for (int i = 0; i < length; i++) {
for (int j = 0; j < width * height; j++) {
int8_t grayscale;
rf.read((char*)&grayscale, 1);
temparray[i][j] = grayscale; //error happens here
}
}
img.setimages(temparray);
rf.close();
return img;
}
int main() {
images testimages;
loadimages("t10k-images.bin", 2051);
cout << testimages.images;
return 0;
}
I don't now how to solve the problem and can't find it anywhere else. Thanks for helping me out.
Your using malloc has done you in.
int* array = (int*)malloc(width* height); // allocate width * height bytes.
array[i] = x; // Sets the [i] _integer_ of array to x.
// but you allocated space for BYTE size elemennts.
The correct way to allocate integers using malloc:
int* array = (int*)malloc(width* height * sizeof(int)); // allocate width * height ints
Either that or your original intent was to allocate 8 bit pixels. In that case, your pointers should be declared as unsigned char*.
In either case, when coding in C++, types are important, and using operator new to allocate your arrays would have saved you from these troubles.

Schedule round robin matches

How to implement a round robin schedule for an array of 4 elements [1,2,3,4]? The result of the algorithm should be able to display, for each element, the list of the players it will face in chronological order:
(1: 4,2,3)
(2: 3,1,4)
(3: 2,4,1)
(4: 1,3,2)
Line 1: 4,2,3 means that the player (1) will face in order the players (4), (2) and (3).
Of the same way, line 2: 3,1,4 indicates that the player (2) will face in order the players (3), (1) and (2).
We have implemented this code but we encounter a bug when we start filling in the name of the player. Do you have any idea about this problem?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_MAX_LENGTH 20
#define NUM_MIN_PLAYERS 2
#define NUM_MAX_PLAYERS 20
enum Style
{
STYLE_COMPACT,
STYLE_TABLE
};
enum Format
{
FORMAT_ID,
FORMAT_NAME
};
struct PlayerList
{
unsigned int num_players;
char name[NUM_MAX_PLAYERS][NAME_MAX_LENGTH + 1];
};
struct Grid
{
unsigned int num_players;
unsigned int day[NUM_MAX_PLAYERS]
[NUM_MAX_PLAYERS];
};
void printList(struct PlayerList *list)
{
for (int i = 0; i < list->num_players; i++)
{
printf("%d:%s\n", i + 1, list->name[i]);
}
}
struct Grid calculer_berger(struct PlayerList *list)
{
struct Grid grid;
// algo pour remplir la grid
grid.num_players = list->num_players;
int i, j;
for (i = 0; i < list->num_players - 1; i++)
{
for (j = 0; j < list->num_players - 1; j++)
{
if (i == j)
{
/* edge cases */
grid.day[i][list->num_players - 1] = ((i + j) + (i + j) / list->num_players) % list->num_players;
grid.day[list->num_players - 1][j] = ((i + j) + (i + j) / list->num_players) % list->num_players;
grid.day[i][j] = 0;
}
else
{
grid.day[i][j] = ((i + j) + (i + j) / list->num_players) % list->num_players;
}
}
}
grid.day[0][list->num_players - 1] = list->num_players - 1;
grid.day[list->num_players - 1][list->num_players - 1] = 0;
grid.day[list->num_players - 1][0] = list->num_players - 1;
return grid;
}
void permuter(struct Grid *grid)
{
int tmp;
for (int i = 0; i < grid->num_players; i++)
{
for (int j = 1; j <= grid->num_players / 2; j++)
{
tmp = grid->day[i][j];
grid->day[i][j] = grid->day[i][grid->num_players - j];
grid->day[i][grid->num_players - j] = tmp;
}
}
}
void print_grid(struct Grid *grid, struct PlayerList *list)
{
for (int i = 0; i < grid->num_players; i++)
{
for (int j = 0; j < grid->num_players; j++)
{
if (j == 0)
{
printf("%d:", grid->day[i][j] + 1);
}
else
{
printf("%d", grid->day[i][j] + 1);
if (j < grid->num_players - 1)
{
printf(",");
}
}
}
printf("\n");
}
}
int main(int argc, char **argv)
{
struct PlayerList playerList;
char nom[NAME_MAX_LENGTH + 1];
int nbCharLu = 0;
while ((nbCharLu = fscanf(stdin, "%s", nom)) != -1)
{
strcpy(playerList.name[playerList.num_players], nom);
playerList.num_players++;
}
struct Grid myGrid = calculer_berger(&playerList);
printList(&playerList);
print_grid(&myGrid, &playerList);
printf("Apres la permut\n");
permuter(&myGrid);
print_grid(&myGrid, &playerList);
return 0;
}
Assuming you are storing the elements in an Integer array and that you would like to just display the results.
Here is one implementation....The code should accommodate "N" values because of the use of "sizeof"....
feel free to customize it further....
#include <stdio.h>
int main() {
int i,j;
int array[] = {1,2,3,4};
for(i = 0; i < sizeof(array)/sizeof(int);++i){
printf("(%d :",array[i]);
for(j = 0; j < sizeof(array)/sizeof(int);++j){
if(j == i)
continue;
printf("%d ",array[j]);
}
printf(")\n");
}
}
#include <stdio.h>
void main() {
int mid;
int num;
int j, temp;
int k = 0;
int num1;
int data[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14};
num = sizeof(data)/sizeof(int);
mid = (sizeof(data)/sizeof(int))/2;
while(k < num - 1){
printf("Round %d ( ",k+1);
num1 = num;
for(int i = 0;i < mid;i++,num1--) /*pairing the competitors in each round*/
printf("%d:%d ",data[i],data[num1-1]);
for(int i = 0,j = num-1; i < num -2;i++,j--){ /* fixing the first competitor and rotating the others clockwise*/
temp = data[j];
data[j] = data[j-1];
data[j-1] = temp;
}
printf(")\n");
k++;
}
}

Image quality improvement in Opencv

I have two images. One has more green color and another one has better quality (it has right color). How can I improve the first one to have the similar color as the second one.I used the contrast enhancement as
//Contrast enhancement
for (int y = 0; y < rotated.rows; y++)
{
for (int x = 0; x < rotated.cols; x++)
{
for (int c = 0; c < 3; c++)
{
//"* Enter the alpha value [1.0-3.0]: "
//"* Enter the beta value [0-100]: ";
rotated.at<Vec3b>(y, x)[c] =
saturate_cast<uchar>(2.5*(rotated.at<Vec3b>(y, x)[c]) + 30);
}
}
}
It brightens the image. But I like to have similar color as the second one. What are the RGB values to change to have the second image's color.
For contrast enhancement you can use the equivalent of Matlab imadjust. You can find an OpenCV implementation here.
Applying imadjust with default parameters on each separate channel you get:
Here the full code:
#include <opencv2\opencv.hpp>
#include <vector>
#include <algorithm>
using namespace std;
using namespace cv;
void imadjust(const Mat1b& src, Mat1b& dst, int tol = 1, Vec2i in = Vec2i(0, 255), Vec2i out = Vec2i(0, 255))
{
// src : input CV_8UC1 image
// dst : output CV_8UC1 imge
// tol : tolerance, from 0 to 100.
// in : src image bounds
// out : dst image buonds
dst = src.clone();
tol = max(0, min(100, tol));
if (tol > 0)
{
// Compute in and out limits
// Histogram
vector<int> hist(256, 0);
for (int r = 0; r < src.rows; ++r) {
for (int c = 0; c < src.cols; ++c) {
hist[src(r, c)]++;
}
}
// Cumulative histogram
vector<int> cum = hist;
for (int i = 1; i < hist.size(); ++i) {
cum[i] = cum[i - 1] + hist[i];
}
// Compute bounds
int total = src.rows * src.cols;
int low_bound = total * tol / 100;
int upp_bound = total * (100 - tol) / 100;
in[0] = distance(cum.begin(), lower_bound(cum.begin(), cum.end(), low_bound));
in[1] = distance(cum.begin(), lower_bound(cum.begin(), cum.end(), upp_bound));
}
// Stretching
float scale = float(out[1] - out[0]) / float(in[1] - in[0]);
for (int r = 0; r < dst.rows; ++r)
{
for (int c = 0; c < dst.cols; ++c)
{
int vs = max(src(r, c) - in[0], 0);
int vd = min(int(vs * scale + 0.5f) + out[0], out[1]);
dst(r, c) = saturate_cast<uchar>(vd);
}
}
}
int main()
{
Mat3b img = imread("path_to_image");
vector<Mat1b> planes;
split(img, planes);
for (int i = 0; i < 3; ++i)
{
imadjust(planes[i], planes[i]);
}
Mat3b result;
merge(planes, result);
return 0;
}

save an image in a complete path

I am using OpenCV library and visual studio 2013. I would like just to save the result image in a complete path. It's ok for the same path but c:\\... doesn't work.
I tried to use both forward \ and back /, the result looked the same.
Here is the code:
#include<iostream>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src, dst;
float sum;
/// Load an image
src = imread("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if (!src.data)
{
return -1;
}
// define the kernel
float Kernel[3][3] = {
{ 1 / 9.0, 1 / 9.0, 1 / 9.0 },
{ 1 / 9.0, 1 / 9.0, 1 / 9.0 },
{ 1 / 9.0, 1 / 9.0, 1 / 9.0 }
};
dst = src.clone();
for (int y = 0; y < src.rows; y++)
for (int x = 0; x < src.cols; x++)
dst.at<uchar>(y, x) = 0.0;
//convolution operation
for (int y = 1; y < src.rows - 1; y++){
for (int x = 1; x < src.cols - 1; x++){
sum = 0.0;
for (int k = -1; k <= 1; k++){
for (int j = -1; j <= 1; j++){
sum = sum + Kernel[j + 1][k + 1] * src.at<uchar>(y - j, x - k);
}
}
dst.at<uchar>(y, x) = sum;
}
}
namedWindow("final");
imshow("final", dst);
namedWindow("initial");
imshow("initial", src);
vector<int> compression_params; //vector that stores the compression parameters of the image
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY); //specify the compression technique
compression_params.push_back(100); //specify the compression quality
bool bSuccess = imwrite("filtre.jpg", dst, compression_params);//ok
bool bSucccess = imwrite("D:/trunk/jpwl/Release/nouveau_dossier/filtre.jpg", dst, compression_params);// not ok
bool bSuccces = imwrite("D:\trunk\jpwl\Release\nouveau_dossier\filtre.jpg", dst, compression_params);// not ok
waitKey();
return 0;
}
Use:
"D:\trunk\jpwl\Release\nouveau_dossier\filtre.jpg" (with double backslash, Stackoverflow also shows a single backslash)
or
#"D:/trunk/jpwl/Release/nouveau_dossier/filtre.jpg"
instead. A single \ is an ESC character.
Dick

Rescaling image in J2ME

I'm resizing a bird image using the following code:
private Image resizeImage(Image src) {
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int screenWidth=getWidth()/3;
int screenHeight=getHeight()/3;
Image tmp = Image.createImage(screenWidth, srcHeight);
Graphics g = tmp.getGraphics();
int ratio = (srcWidth << 16) / screenWidth;
int pos = ratio/2;
//Horizontal Resize
for (int x = 0; x < screenWidth; x++) {
g.setClip(x, 0, 1, srcHeight);
g.drawImage(src, x - (pos >> 16), 0, Graphics.LEFT | Graphics.TOP);
pos += ratio;
}
Image resizedImage = Image.createImage(screenWidth, screenHeight);
g = resizedImage.getGraphics();
ratio = (srcHeight << 16) / screenHeight;
pos = ratio/2;
//Vertical resize
for (int y = 0; y < screenHeight; y++) {
g.setClip(0, y, screenWidth, 1);
g.drawImage(tmp, 0, y - (pos >> 16), Graphics.LEFT | Graphics.TOP);
pos += ratio;
}
return resizedImage;
}
The image is resized but it has white background along with it as shown. How to get only resized image with transparent background..?
Here is an Image scaling function I've been using. Includes transparency. Found here: http://willperone.net/Code/codescaling.php
public Image scale(Image original, int newWidth, int newHeight) {
int[] rawInput = new int[original.getHeight() * original.getWidth()];
original.getRGB(rawInput, 0, original.getWidth(), 0, 0, original.getWidth(), original.getHeight());
int[] rawOutput = new int[newWidth * newHeight];
// YD compensates for the x loop by subtracting the width back out
int YD = (original.getHeight() / newHeight) * original.getWidth() - original.getWidth();
int YR = original.getHeight() % newHeight;
int XD = original.getWidth() / newWidth;
int XR = original.getWidth() % newWidth;
int outOffset = 0;
int inOffset = 0;
for (int y = newHeight, YE = 0; y > 0; y--) {
for (int x = newWidth, XE = 0; x > 0; x--) {
rawOutput[outOffset++] = rawInput[inOffset];
inOffset += XD;
XE += XR;
if (XE >= newWidth) {
XE -= newWidth;
inOffset++;
}
}
inOffset += YD;
YE += YR;
if (YE >= newHeight) {
YE -= newHeight;
inOffset += original.getWidth();
}
}
rawInput = null;
return Image.createRGBImage(rawOutput, newWidth, newHeight, true);
}

Resources