How to improve otsu threshold output - c++

I am using otsu threshold on an image.
Here is the input image :
Here is the output :
Here is the code I am using:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
using namespace cv;
int main(int argc, char const *argv[]) {
title("Text Extractor");
string win_name = "textextractor";
Mat img_a;
img_a = imread("../input/test_c.jpg");
Mat img_a_gray;
cvtColor(img_a, img_a_gray, CV_BGR2GRAY);
Mat img_a_blur;
GaussianBlur(img_a_gray, img_a_blur, Size(3, 3), 0, 0);
Mat img_a_thres;
// adaptiveThreshold(img_a_blur, img_a_thres, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 5, 4);
threshold(img_a_blur, img_a_thres, 0, 255, THRESH_OTSU);
namedWindow(win_name + "_a", CV_WINDOW_AUTOSIZE);
imshow(win_name + "_a", img_a_thres);
imwrite("../output/output_a.jpg", img_a_thres);
waitKey(0);
return 0;
}
The problem is that output has a black region on the bottom and on the left. What can I do to minimize/remove this ?
Edit:
I tried equalizeHist() and I am getting this:
Will try out breaking image into pieces and working them separately.
Sorry, my bad. The previous one is using adaptive filtering. Using Otsu I get this:
There is no change in otsu's output :/
Edit 2: Completed the Feng Tan algorithm, it gives better results but text looses clarity.
Code:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/photo/photo.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
using namespace cv;
int main(int argc, char const *argv[]) {
string win_name = "textextractor";
Mat img_c;
img_c = imread("../input/sample.jpg");
Mat img_c_gray;
cvtColor(img_c, img_c_gray, CV_BGR2GRAY);
Mat img_c_bin = Mat::zeros(img_c_gray.rows, img_c_gray.cols, CV_8UC1);
int s_win = 17;
int l_win = 35;
double min_tau = 10;
Rect roi_s = Rect(-s_win/2, -s_win/2, s_win, s_win);
Rect roi_l = Rect(-l_win/2, -l_win/2, l_win, l_win);
Rect img_c_roi = Rect(0, 0, img_c_gray.cols, img_c_gray.rows);
for (size_t r = 0; r < img_c_gray.rows; r++) {
for (size_t c = 0; c < img_c_gray.cols; c++) {
double pthres = 255;
Rect sROI = roi_s + Point(c, r);
sROI = sROI & img_c_roi;
if(sROI.width == 0 || sROI.height == 0) {
continue;
}
Rect lROI = roi_l + Point(c, r);
lROI = lROI & img_c_roi;
if(lROI.width == 0 || lROI.height == 0) {
continue;
}
Mat sROI_gray = img_c_gray(sROI);
Mat lROI_gray = img_c_gray(lROI);
double s_stdDev = 0;
double l_stdDev = 0;
double s_mean = 0;
double l_mean = 0;
double l_min = DBL_MAX;
for (size_t r = 0; r < sROI_gray.rows; r++) {
for (size_t c = 0; c < sROI_gray.cols; c++) {
s_mean += sROI_gray.at<unsigned char>(r, c);
}
}
s_mean = s_mean / static_cast<double> (sROI_gray.cols * sROI_gray.rows);
for (size_t r = 0; r < sROI_gray.rows; r++) {
for (size_t c = 0; c < sROI_gray.cols; c++) {
double diff = sROI_gray.at<unsigned char> (r, c) - s_mean;
s_stdDev += diff * diff;
}
}
s_stdDev = sqrt(s_stdDev / static_cast<int> (sROI_gray.cols * sROI_gray.rows));
for (size_t r = 0; r < lROI_gray.rows; r++) {
for (size_t c = 0; c < lROI_gray.cols; c++) {
l_mean += lROI_gray.at<unsigned char> (c, r);
if(lROI_gray.at<unsigned char> (r, c) < l_min) {
l_min = lROI_gray.at<unsigned char> (r, c);
}
}
}
l_mean = l_mean / static_cast<double> (lROI_gray.cols * lROI_gray.rows);
for (size_t r = 0; r < lROI_gray.rows; r++) {
for (size_t c = 0; c < lROI_gray.cols; c++) {
double diff = lROI_gray.at<unsigned char> (r, c) - l_mean;
l_stdDev += diff * diff;
}
}
l_stdDev = sqrt(l_stdDev / static_cast<double> (lROI_gray.cols * lROI_gray.rows));
double tau = ((s_mean - l_min) * (1 - s_stdDev / l_stdDev)) / 2.0;
if(tau < min_tau) {
tau = min_tau;
}
double threshold = s_mean - tau;
unsigned char pixel_val = img_c_gray.at<unsigned char>(r, c);
if(pixel_val >= threshold) {
img_c_bin.at<unsigned char> (r, c) = 255;
} else {
img_c_bin.at<unsigned char> (r, c) = 0;
}
}
}
namedWindow(win_name + "_c", CV_WINDOW_AUTOSIZE);
imshow(win_name + "_c", img_c_bin);
imwrite("../output/output_c.jpg", img_c_bin);
waitKey(0);
return 0;
}
Output:

This is what I was able to obtain after some trial and run. Initially I median blurred the original image. Then I applied adpative threshold to the blurred image.
This is what I got:
1. Adaptive Threshold using Gaussian filter:
2. Adaptive Threshold using Mean filter:
From here on you can carry out a series of morphological operations that best suits your final image. :)

You should try using CLAHE.
I tried it on MATLAB using:
Ia = imread('FHXTJ.jpg');
I = rgb2gray(Ia);
A = adapthisteq(I, 'clipLimit', 0.02, 'Distribution', 'rayleigh');
Result:
Note: You can apply thresholding on this image. Otsu should work fine now.

Related

different value of thresh - converting Matlab code to OpenCV code

I would like some help regarding passing a code that is in matlab to opencv c ++. I am trying to do some operations with the RGB channels, however, the value of thresh is not being the same - I am sending the same image. Could someone please help me?
MATLAB
im = imread('1.png');
[m,n,p] = size(im);
R=im(:, :, 1);
G=im(:, :, 2);
B=im(:, :, 3);
thresh=0;
for j=1:n
for i=1:m
thresh = thresh + double((1.262*G(i,j))-(0.884*R(i,j))-(0.311*B(i,j)));
end
end
C++
#include <opencv2/opencv.hpp>
#include "opencv2/highgui.hpp"
#include <opencv2/core/mat.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(){
Mat img = imread("1.png", IMREAD_COLOR);
int thresh = 0;
for(int j = 0; j <= img.cols; j++){
for(int i = 0; i <= img.rows; i++){
Vec3b color = img.at<Vec3b>(i,j);
uchar a = color.val[0], b = color.val[1], c = color.val[2];
thresh += double((1.262*b)-(0.884*c)-(0.311*a));
}
}
cout << thresh;
return 0;
}
First mistake is in the upper values of for loops because you are exceeding the range of image borders.
j <= img.cols should be j < img.cols and
i <= img.rows should be i < img.rows
Second mistake is that you don't make explicit type conversion for your uchar type pixel values
thresh += double((1.262*b)-(0.884*c)-(0.311*a));
should be
thresh += double((1.262*static_cast<double>(b))
-(0.884*static_cast<double>(c))
-(0.311*static_cast<double>(a)));
Here is the whole code I tried:
#include <opencv2/opencv.hpp>
#include "opencv2/highgui.hpp"
#include <opencv2/core/mat.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("img.jpg", IMREAD_COLOR);
double thresh = 0.0;
resize(img,img,Size(100,100));
for(int j = 0; j < img.cols; j++){
for(int i = 0; i < img.rows; i++){
// 1ST WAY
Vec3b color = img.at<Vec3b>(i,j);
uchar a = color.val[0], b = color.val[1], c = color.val[2];
thresh += double((1.262*static_cast<double>(b))
-(0.884*static_cast<double>(c))
-(0.311*static_cast<double>(a)));
// 2ND WAY
// thresh += double((1.262 * (double)img.at<Vec3b>(Point(i,j))[1])
// - (0.884*(double)img.at<Vec3b>(Point(i,j))[2])
// - (0.311 * (double)img.at<Vec3b>(Point(i,j))[0]));
}
}
cout << thresh << endl;
return 0;
}

Max entropy thresholding using OpenCV [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to convert the code for using the maximum entropy thresholding from this matlab code:
%**************************************************************************
%**************************************************************************
%
% maxentropie is a function for thresholding using Maximum Entropy
%
%
% input = I ==> Image in gray level
% output =
% I1 ==> binary image
% threshold ==> the threshold choosen by maxentropie
%
% F.Gargouri
%
%
%**************************************************************************
%**************************************************************************
function [threshold I1]=maxentropie(I)
[n,m]=size(I);
h=imhist(I);
%normalize the histogram ==> hn(k)=h(k)/(n*m) ==> k in [1 256]
hn=h/(n*m);
%Cumulative distribution function
c(1) = hn(1);
for l=2:256
c(l)=c(l-1)+hn(l);
end
hl = zeros(1,256);
hh = zeros(1,256);
for t=1:256
%low range entropy
cl=double(c(t));
if cl>0
for i=1:t
if hn(i)>0
hl(t) = hl(t)- (hn(i)/cl)*log(hn(i)/cl);
end
end
end
%high range entropy
ch=double(1.0-cl); %constraint cl+ch=1
if ch>0
for i=t+1:256
if hn(i)>0
hh(t) = hh(t)- (hn(i)/ch)*log(hn(i)/ch);
end
end
end
end
% choose best threshold
h_max =hl(1)+hh(1)
threshold = 0;
entropie(1)=h_max;
for t=2:256
entropie(t)=hl(t)+hh(t);
if entropie(t)>h_max
h_max=entropie(t);
threshold=t-1;
end
end
% Display
I1 = zeros(size(I));
I1(I<threshold) = 0;
I1(I>threshold) = 255;
%imshow(I1)
end
The problem is that I'm getting floating point excpetion error in the code, and I cannot understand why
This is my implementation:
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <math.h>
using namespace cv;
using namespace std;
int main(){
cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
cout.precision(9);
Mat old_image=imread("2.png",CV_LOAD_IMAGE_GRAYSCALE);
double minval, maxval;
minMaxLoc(old_image,&minval, &maxval);
cout<<minval<<" "<<maxval<<endl;
Mat image;
old_image.convertTo(image, CV_8UC1, 255.0/(maxval-minval), -minval*255.0/(maxval-minval));
minMaxLoc(image,&minval, &maxval);
cout<<minval<<" "<<maxval;
int k=0;
imshow("im",image);
waitKey(0);
for(int y=0; y<image.rows;y++){
for(int x=0; x<image.cols;x++){
if((int) image.at<uchar>(y,x)==0){
k++;
}
}
}
cout<<k<<endl<<endl;
int i, l, j, t;
int histSize = 256;
float range[] = { 0, 255 };
const float *ranges[] = { range };
Mat hist, histogram, c, ctmp, hl, hh, hhtmp, entropy;
calcHist( &image, 1, 0, Mat(), hist, 1, &histSize, ranges, true, false );
for( int h = 1; h < histSize; h++){
histogram.push_back(hist.at<float>(h,0));
cout<<histogram.rows<<endl;
cout<<histogram.row(h-1)<<endl;
cout<<hist.row(h)<<endl;
}
histogram=histogram/(image.rows*image.cols-hist.at<float>(0,0));
//cumulative distribution function
float cl,ch;
ctmp.push_back(histogram.row(0));
c.push_back(histogram.row(0));
cout<<c.row(0)<<endl;
for(l=1;l<255;l++){
c.push_back(ctmp.at<float>(0)+histogram.at<float>(l));
ctmp.push_back(c.row(l));
cout<<c.at<float>(l)<<endl;
//c.row(l)=c.row(l-1)+histogram.row(l);
}
Mat hltmp= Mat::zeros(1,256,CV_8U);
// THE PROBLEM IS IN THIS TWO FOR CYCLES
for(t=0;t<255;t++){
//low range entropy
cl=c.at<float>(t);
if(cl>0){
for(i=0;i<=t;i++){
if(histogram.at<float>(t)>0){
printf("here\n");
hl.push_back(hltmp.at<float>(0)-(histogram.at<float> (i)/cl)*log(histogram.at<float>(i)/cl));
printf("here\n");
cout<<hl.at<float>(i);
printf("here\n");
hltmp.push_back(hl.row(t));
printf("here\n");
}
}
}
printf("here\n");
//high range entropy
ch=1.0-cl;
if(ch>0){
for(i=t+1;i<255;i++){
if(histogram.at<float>(i)>0){
hh.push_back(hh.at<float>(t)-(histogram.at<float> (i)/ch)*log(histogram.at<float>(i)/ch));
}
}
}
}
//choose the best threshold
float h_max=hl.at<float>(0,0)+hh.at<float>(0,0);
float threshold=0;
entropy.at<float>(0,0)=h_max;
for(t=1;t<255;t++){
entropy.at<float>(t)=hl.at<float>(t)+hh.at<float>(t);
if(entropy.at<float>(t)>h_max){
h_max=entropy.at<float>(t);
threshold=t-1;
}
cout<<threshold<<endl;
}
//display
Mat I1= Mat::zeros(image.rows,image.cols,CV_8UC1);
for(int y=0; y<image.rows;y++){
for(int x=0; x<image.cols;x++){
if((int) image.at<uchar>(y,x)<threshold){
I1.at<uchar>(y,x)=0;
}
else{
I1.at<uchar>(y,x)=255;
}
}
}
imshow("image",I1);
waitKey(0);*/
return 0;
}
Your problem is that you're reading float elements from a CV_8U (aka uchar) Mat.
Mat hltmp = Mat::zeros(1, 256, CV_8U);
...
hltmp.at<float>(0)
You should learn how to use a debugger, and you'll find out these problems very soon.
Since you over-complicated things in your implementation, made some errors, and the code is cluttered from debug prints, I propose the one below instead of punctually correct your (not many, but mainly conceptual) errors. You can see that, if written properly, there is almost a 1:1 conversion from Matlab to OpenCV.
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
uchar maxentropie(const Mat1b& src, Mat1b& dst)
{
// Histogram
Mat1d hist(1, 256, 0.0);
for (int r=0; r<src.rows; ++r)
for (int c=0; c<src.cols; ++c)
hist(src(r,c))++;
// Normalize
hist /= double(src.rows * src.cols);
// Cumulative histogram
Mat1d cumhist(1, 256, 0.0);
float sum = 0;
for (int i = 0; i < 256; ++i)
{
sum += hist(i);
cumhist(i) = sum;
}
Mat1d hl(1, 256, 0.0);
Mat1d hh(1, 256, 0.0);
for (int t = 0; t < 256; ++t)
{
// low range entropy
double cl = cumhist(t);
if (cl > 0)
{
for (int i = 0; i <= t; ++i)
{
if (hist(i) > 0)
{
hl(t) = hl(t) - (hist(i) / cl) * log(hist(i) / cl);
}
}
}
// high range entropy
double ch = 1.0 - cl; // constraint cl + ch = 1
if (ch > 0)
{
for (int i = t+1; i < 256; ++i)
{
if (hist(i) > 0)
{
hh(t) = hh(t) - (hist(i) / ch) * log(hist(i) / ch);
}
}
}
}
// choose best threshold
Mat1d entropie(1, 256, 0.0);
double h_max = hl(0) + hh(0);
uchar threshold = 0;
entropie(0) = h_max;
for (int t = 1; t < 256; ++t)
{
entropie(t) = hl(t) + hh(t);
if (entropie(t) > h_max)
{
h_max = entropie(t);
threshold = uchar(t);
}
}
// Create output image
dst = src > threshold;
return threshold;
}
int main()
{
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
Mat1b res;
uchar th = maxentropie(img, res);
imshow("Original", img);
imshow("Result", res);
waitKey();
return 0;
}

Finding only big blobs on image

Hello I'm trying to find characters on this image.
This is my image after some preprocessing I recieved this image.
Now I'm trying to do connected component labeling to find blobs. however I get a lot of small blobs too.
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
void FindBlobs(const Mat &binary, vector < vector<Point2i> > &blobs);
int main(int argc, char **argv)
{
Mat img = imread("adaptive.png", 0);
if(!img.data) {
cout << "File not found" << endl;
return -1;
}
namedWindow("binary");
namedWindow("labelled");
Mat output = Mat::zeros(img.size(), CV_8UC3);
Mat binary;
vector < vector<Point2i > > blobs;
threshold(img, binary, 0, 1, THRESH_BINARY_INV);
FindBlobs(binary, blobs);
// Randomy color the blobs
for(size_t i=0; i < blobs.size(); i++) {
unsigned char r = 255 * (rand()/(1.0 + RAND_MAX));
unsigned char g = 255 * (rand()/(1.0 + RAND_MAX));
unsigned char b = 255 * (rand()/(1.0 + RAND_MAX));
for(size_t j=0; j < blobs[i].size(); j++) {
int x = blobs[i][j].x;
int y = blobs[i][j].y;
output.at<Vec3b>(y,x)[0] = b;//Vec3b RGB color order
output.at<Vec3b>(y,x)[1] = g;
output.at<Vec3b>(y,x)[2] = r;
}
}
imshow("binary", img);
imshow("labelled", output);
waitKey(0);
return 0;
}
void FindBlobs(const Mat &binary, vector < vector<Point2i> > &blobs)
{
blobs.clear();
Mat label_image;
binary.convertTo(label_image, CV_32SC1);
int label_count = 2; // starts at 2 because 0,1 are used already
for(int y=0; y < label_image.rows; y++) {
int *row = (int*)label_image.ptr(y);
for(int x=0; x < label_image.cols; x++) {
if(row[x] != 1) {
continue;
}
Rect rect;
floodFill(label_image, Point(x,y), label_count, &rect, 0, 0, 4);
vector <Point2i> blob;
for(int i=rect.y; i < (rect.y+rect.height); i++) {
int *row2 = (int*)label_image.ptr(i);
for(int j=rect.x; j < (rect.x+rect.width); j++) {
if(row2[j] != label_count) {
continue;
}
blob.push_back(Point2i(j,i));
}
}
blobs.push_back(blob);
label_count++;
}
}
}
so with this algorithm I recieve blobs
but when I do
if(blobs.size()>50) {
blob.push_back(Point2i(j,i));
}
I recieve black screen. however when I try to
if(blob.size()<50){
blob.push_back(Point2i(j,i));
}
I recieve small blobs what can be the actual problem here ?
Guess you want to store those "big" blobs?
If so, change the following code
blobs.push_back(blob);
label_count++;
to this:
if(blob.size() > 50){
blobs.push_back(blob);
}
label_count++;
And you can receive picture like this:

Different results with cvDFT and DFT in OpenCV 2.4.8

I'm having problems with the DFT function in OpenCV 2.4.8 for c++.
I used an image of a 10 phases sinus curve to compare the old cvDFT() with the newer c++ function DFT() (one dimensional DFT row-wise).
The old version gives me logical results: very high peak at pixel 0 and 10, the rest being almost 0.
The new version gives me strange results with peaks all over the spectrum.
Here is my code:
#include "stdafx.h"
#include <opencv2\core\core_c.h>
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc_c.h>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui_c.h>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\legacy\compat.hpp>
using namespace cv;
void OldMakeDFT(Mat original, double* result)
{
const int width = original.cols;
const int height = 1;
IplImage* fftBlock = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
IplImage* imgReal = cvCreateImage(cvSize(width, height), IPL_DEPTH_32F, 1);
IplImage* imgImag = cvCreateImage(cvSize(width, height), IPL_DEPTH_32F, 1);
IplImage* imgDFT = cvCreateImage(cvSize(width, height), IPL_DEPTH_32F, 2);
Rect roi(0, 0, width, 1);
Mat image_roi = original(roi);
fftBlock->imageData = (char*)image_roi.data;
//cvSaveImage("C:/fftBlock1.png", fftBlock);
cvConvert(fftBlock, imgReal);
cvMerge(imgReal, imgImag, NULL, NULL, imgDFT);
cvDFT(imgDFT, imgDFT, (CV_DXT_FORWARD | CV_DXT_ROWS));
cvSplit(imgDFT, imgReal, imgImag, NULL, NULL);
double re,imag;
for (int i = 0; i < width; i++)
{
re = ((float*)imgReal->imageData)[i];
imag = ((float*)imgImag->imageData)[i];
result[i] = re * re + imag * imag;
}
cvReleaseImage(&imgReal);
cvReleaseImage(&imgImag);
cvReleaseImage(&imgDFT);
cvReleaseImage(&fftBlock);
}
void MakeDFT(Mat original, double* result)
{
const int width = original.cols;
const int height = 1;
Mat fftBlock(1,width, CV_8UC1);
Rect roi(0, 0, width, height);
Mat image_roi = original(roi);
image_roi.copyTo(fftBlock);
//imwrite("C:/fftBlock2.png", fftBlock);
Mat planes[] = {Mat_<float>(fftBlock), Mat::zeros(fftBlock.size(), CV_32F)};
Mat complexI;
merge(planes, 2, complexI);
dft(complexI, complexI, DFT_ROWS); //also tried with DFT_COMPLEX_OUTPUT | DFT_ROWS
split(complexI, planes);
double re, imag;
for (int i = 0; i < width; i++)
{
re = (float)planes[0].data[i];
imag = (float)planes[1].data[i];
result[i] = re * re + imag * imag;
}
}
bool SinusFFTTest()
{
const int size = 1024;
Mat sinTest(size,size,CV_8UC1, Scalar(0));
const int n_sin_curves = 10;
double deg_step = (double)n_sin_curves*360/size;
for (int j = 0; j < size; j++)
{
for (int i = 0; i <size; i++)
{
sinTest.data[j*size+i] = 127.5 * sin(i*deg_step*CV_PI/180) + 127.5;
}
}
double* result1 = new double[size];
double* result2 = new double[size];
OldMakeDFT(sinTest,result1);
MakeDFT(sinTest,result2);
bool identical = true;
for (int i = 0; i < size; i++)
{
if (abs(result1[i] - result2[i]) > 1000)
{
identical = false;
break;
}
}
delete[] result1;
delete[] result2;
return identical;
}
int _tmain(int argc, _TCHAR* argv[])
{
if (SinusFFTTest())
{
printf("identical");
}
else
{
printf("different");
}
getchar();
return 0;
}
Could someone explain the difference?
imgReal - is not filled with zeroes by default.
The bug in in the MakeDFT() function:
re = (float)planes[0].data[i];
imag = (float)planes[1].data[i];
data[i]'s type is uchar, and its conversion to float is not right.
The fix:
re = planes[0].at<float>(0,i);
imag = planes[1].at<float>(0,i);
After this change, the old and the new DFT versions gives the same results. Or, you can use cv::magnitude() instead of calculating the sum of squares of re and imag:
Mat magn;
magnitude(planes[0], planes[1], magn);
for (int i = 0; i < width; i++)
result[i] = pow(magn.at<float>(0,i),2);
This gives also the same result as the old cvDFT.

Changing brightness and contrast of an image

I am working on the following code
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Mat change(Mat m);
int main()
{
Mat image = imread("C:/Users/Public/Pictures/Sample Pictures/Penguins.jpg");
Mat copy = Mat::zeros(image.size(),image.type());
Mat changedImage = change(copy);
namedWindow("Image");
imshow("Image",changedImage);
waitKey(0);
}
Mat change(Mat m)
{
int cols = m.cols;
int rows = m.rows;
double alpha = 2.2;
int beta = 50;
for(int i=0;i<rows;i++)
{
for(int c=0;c<cols;c++)
{
m.at<Vec3b>(rows,c)[0] = saturate_cast<uchar>(alpha* (m.at<Vec3b>(rows,cols)[0]) + beta);
m.at<Vec3b>(rows,c)[1] = saturate_cast<uchar>(alpha* (m.at<Vec3b>(rows,cols)[1]) + beta);
m.at<Vec3b>(rows,c)[2] = saturate_cast<uchar>(alpha* (m.at<Vec3b>(rows,cols)[2]) + beta);
}
}
return m;
}
This compiles fine, but when I run this, I get the following error
OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)si
ze.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channel
s()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3
) - 1))*4) & 15) == elemSize1()) in unknown function, file c:\opencv\build\inclu
de\opencv2\core\mat.hpp, line 534
Why I am getting this? I guess I have done everything correctly.
Try this code.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Mat change(Mat m);
int main()
{
Mat image = imread("C:/Users/Public/Pictures/Sample Pictures/Penguins.jpg");
Mat changedImage = change(image); //Modified
namedWindow("Image");
imshow("Image",changedImage);
waitKey(0);
}
Mat change(Mat m)
{
int cols = m.cols;
int rows = m.rows;
double alpha = 2.2;
int beta = 50;
for(int i=0;i<rows;i++)
{
for(int c=0;c<cols;c++)
{
m.at<Vec3b>(i,c)[0] = saturate_cast<uchar>(alpha* (m.at<Vec3b>(i,c))[0]) + beta); //Modified
m.at<Vec3b>(i,c)[1] = saturate_cast<uchar>(alpha* (m.at<Vec3b>(i,c))[1]) + beta); //Modified
m.at<Vec3b>(i,c)[2] = saturate_cast<uchar>(alpha* (m.at<Vec3b>(i,c))[2]) + beta); //Modified
}
}
return m;
}
Try this...
Mat Change(Mat input,int beta = 50)
{
Mat Output;
Scalar S(beta,beta,beta);
cv::add(input,S,Output);
return Output;
}