I have found a program which can binarize an image and make the image monochrome
OpenCV Adaptive Threshold OCR
I have copy/pasted the code
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdarg.h>
#include "/usr/include/opencv2/opencv.hpp"
#include "fstream"
#include "iostream"
using namespace std;
using namespace cv;
void CalcBlockMeanVariance(Mat& Img,Mat& Res,float blockSide=21) // blockSide - the parameter (set greater for larger font on image)
{
Mat I;
Img.convertTo(I,CV_32FC1);
Res=Mat::zeros(Img.rows/blockSide,Img.cols/blockSide,CV_32FC1);
Mat inpaintmask;
Mat patch;
Mat smallImg;
Scalar m,s;
for(int i=0;i<Img.rows-blockSide;i+=blockSide)
{
for (int j=0;j<Img.cols-blockSide;j+=blockSide)
{
patch=I(Range(i,i+blockSide+1),Range(j,j+blockSide+1));
cv::meanStdDev(patch,m,s);
if(s[0]>0.01) // Thresholding parameter (set smaller for lower contrast image)
{
Res.at<float>(i/blockSide,j/blockSide)=m[0];
}else
{
Res.at<float>(i/blockSide,j/blockSide)=0;
}
}
}
cv::resize(I,smallImg,Res.size());
cv::threshold(Res,inpaintmask,0.02,1.0,cv::THRESH_BINARY);
Mat inpainted;
smallImg.convertTo(smallImg,CV_8UC1,255);
inpaintmask.convertTo(inpaintmask,CV_8UC1);
inpaint(smallImg, inpaintmask, inpainted, 5, INPAINT_TELEA);
cv::resize(inpainted,Res,Img.size());
Res.convertTo(Res,CV_32FC1,1.0/255.0);
}
int main( int argc, char** argv )
{
namedWindow("Img");
namedWindow("Edges");
//Mat Img=imread("D:\\ImagesForTest\\BookPage.JPG",0);
Mat Img=imread("Test2.JPG",0);
Mat res;
Img.convertTo(Img,CV_32FC1,1.0/255.0);
CalcBlockMeanVariance(Img,res);
res=1.0-res;
res=Img+res;
imshow("Img",Img);
cv::threshold(res,res,0.85,1,cv::THRESH_BINARY);
cv::resize(res,res,cv::Size(res.cols/2,res.rows/2));
imwrite("result.jpg",res*255);
imshow("Edges",res);
waitKey(0);
return 0;
}
compile
g++ binarize.cpp `pkg-config opencv --cflags --libs`
run
./a.out
error
(Img:27277): Gtk-WARNING **: cannot open display:
update
int main( int argc, char** argv )
{
namedWindow("Img");
namedWindow("Edges");
//Mat Img=imread("D:\\ImagesForTest\\BookPage.JPG",0);
Mat Img=imread("Test2.JPG",0);
Mat res;
Img.convertTo(Img,CV_32FC1,1.0/255.0);
CalcBlockMeanVariance(Img,res);
res=1.0-res;
res=Img+res;
imshow("Img",Img);
cv::threshold(res,res,0.85,1,cv::THRESH_BINARY);
cv::resize(res,res,cv::Size(res.cols/2,res.rows/2));
imwrite("result.tif",res*255);
imshow("Edges",res);
waitKey(0);
return 0;
}
Just built this code on ubuntu 14.03 x64, using the same command line as you used, no any messages, runs fine.
I think warning related to your system environment.
Related
I have written a simple code to perform canny edge detection on a live stream. The code is as shown below,
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int lowThreshold=0;
int const max_lowThreshold = 100;
int kernel_size = 3;
int ratio = 3;
Mat img;
Mat display;
void CannyThreshold()
{
cvtColor(img, display, COLOR_RGB2GRAY);
// GaussianBlur(display,display,Size(7,7),3,3);
GaussianBlur(display, display, Size(1, 1), 1,1);
printf("%d\n",lowThreshold);
Canny(display,display,lowThreshold,3);
imshow("Canny",display);
}
int main()
{
VideoCapture cap(0);
namedWindow("Canny");
createTrackbar("Min Threshold: ","Canny",&lowThreshold,max_lowThreshold);
while(1)
{
cap.read(img);
int ret = waitKey(1);
CannyThreshold();
if(ret == 'q')
break;
}
cap.release();
return 0;
}
I get the following run-time error when I run the code. (I'm using OpenCV 4)
error: (-215:Assertion failed) ksize.width > 0 && ksize.width % 2 == 1 && ksize.height > 0 && ksize.height % 2 == 1 in function 'createGaussianKernels'
Any suggestions on how I can solve this error?
The issue is GaussianBlur cant accept kernel size of 1. Correct it to 3x3 or 5x5 in your code as follows
#include <opencv2/core/utility.hpp>
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
#include <ctype.h>
using namespace cv;
using namespace std;
int main(int argc, const char** argv)
{
VideoCapture cap;
Mat frame;
Mat image; // from cap to image
Mat src_gray;
Mat dst;
Mat detected_edges;
const String window_name = "Canny Edge Detector - VideoCapture";
int lowThreshold = 10;
const int max_lowThreshold = 100;
const int ratio = 3;
const int kernel_size = 3;
int FPS;
int frame_width, frame_height;
int camNum = 0;
cap.open(camNum);
if (!cap.isOpened())
{
cout << "***Could not initialize capturing...***\n";
cout << "Current parameter's value: \n";
return -1;
}
FPS = cap.get(CAP_PROP_FPS);
frame_width = cap.get(CAP_PROP_FRAME_WIDTH);
frame_height = cap.get(CAP_PROP_FRAME_HEIGHT);
dst.create(frame_width, frame_height, CV_8UC3);
//cout << CV_8UC3;
while (true)
{
cap >> frame;
if (frame.empty())
break;
frame.copyTo(image);
// Convert the image to grayscale
cvtColor(image, src_gray, COLOR_BGR2GRAY);
//![reduce_noise]
/// Reduce noise with a kernel 3x3
blur(src_gray, detected_edges, Size(3, 3));
//![reduce_noise]
//![canny]
/// Canny detector
Canny(detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size);
//![canny]
/// Using Canny's output as a mask, we display our result
//![fill]
dst = Scalar::all(0);
//![fill]
//![copyto]
image.copyTo(dst, detected_edges);
//![copyto]
//![display]
imshow(window_name, dst);
if (waitKey(1000 / FPS) >= 0)
break;
}
return 0;
}
I am trying to read video file, but its throwing error.
The code is:
#include <iostream>
#include <opencv/highgui.h>
#include <opencv/cv.h>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char* argv[])
{
Mat inputVideo;
Mat frame;
Mat HSV;
Mat tracking;
char checkKey;
VideoCapture capture;
capture.open("video/input.mp4");
capture.set(CV_CAP_PROP_FRAME_WIDTH, 640);
capture.set(CV_CAP_PROP_FRAME_HEIGHT,480);
namedWindow("Original Video", WINDOW_AUTOSIZE );
while(1){
capture.read(inputVideo);
if (!inputVideo.empty())
{
imshow("Original Video",inputVideo);
}
waitKey(20);
}
return 0;
}
On running this code, the error I am getting is:
Unable to stop the stream: Inappropriate ioctl for device
(video_reading:3459): GLib-GObject-CRITICAL **: g_object_set:
assertion 'G_IS_OBJECT (object)' failed
I tried looking for solutions, but i did not get it. Can some one help me in solving this error.
I made little changes in your code. Try this:
#include <iostream>
#include <opencv/highgui.h>
#include <opencv/cv.h>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char* argv[])
{
Mat inputVideo;
Mat frame;
Mat HSV;
Mat tracking;
char checkKey;
VideoCapture capture;
capture.open("video/input.mp4");
capture.set(CV_CAP_PROP_FRAME_WIDTH, 640);
capture.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
namedWindow("Original Video", WINDOW_AUTOSIZE);
while (1) {
capture >> inputVideo;
if (inputVideo.empty())
break;
imshow("Original Video", inputVideo);
waitKey(1);
}
capture.release();
return 0;
}
I am trying to make a simple conversion of an image from RGB to Grayscale with OpenCV. I am using dev-cp on windows, here is the code:
#include <cv.h>
#include <highgui.h>
using namespace cv;
int main( int argc, char** argv )
{
char* imageName = argv[1];
Mat image;
image = imread( imageName );
Mat gray_image;
cvtColor(image,gray_image,CV_RGB2GRAY);
}
When I execute it, seems it crashes on the cvtColor.
please try
#include <cv.h>
#include <highgui.h>
using namespace cv;
int main( int argc, char** argv )
{
if (argc < 2) return 0;
char* imageName = argv[1];
Mat image;
image = imread( imageName );
if(image.empty()) return 0;
Mat gray_image;
cvtColor(image,gray_image,CV_RGB2GRAY);
imshow("image",image);
cv::waitKey(0);
return 0;
}
I have an IplImage and I want to binarize (without using cvThreshold function) it using this following code:
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
static IplImage* img ;
img = cvLoadImage ("c:\\Mytest.jpg");
for(int i=0;i<img->height;i++)
{
for(int j=0;j<img->width;j++)
{
if (img->imageData[i*img->widthStep+j]<=10)
((uchar *)img->imageData)[i*img->widthStep+j]=255;
else
((uchar *)img->imageData)[i*img->widthStep+j]=0;
}
}
cvShowImage("After",img);
waitKey(0);
};
but this code affected only part of the image, like this:
see, it's a breeze with c++:
Mat img = imread("c:\\Mytest.jpg", 0); // load grayscale
Mat thresh = ( im <= 10 ); // that's it already!
imshow("After",img);
waitKey(0);
also look at threshold()
I've got myself in a pickle on this project I'm working on. My main objective is to stitch two webcam feeds together and do object detection on them - bounding boxes, etc...the standard stuff.
I can't rid myself of buffer overflows though - the somewhat simplified code below (for readability) compiles x64 and soon after I get a buffer overflow error and this in the console:
"OpenCV Error: Assertion Failed (contour.checkVector(2) >= 0 && (contour.depth() == CV_32F || CV_32S) in unknown function, file...."
If comment out all of the lines that have to do with contours (from findContours to drawBoundingBoxes in main) it compiles and runs fine until I hit the spacebar to stop the program, and then I get another buffer overflow error. I get the same errors when I compile x32 as well, for the record.
Any help? Relevant code/pseudo-code pasted below:
// **defines.h**
//Definitions for anything in all caps, like WIDTH, HEIGHT, ERODEIT, etc...
// **protos.h**
// All function prototypes, nothing else
// **detection.cpp**
/* This is the code that related to background subtraction operations*/
#include <opencv2/opencv.hpp>
#include <iostream>
#include "defines.h"
using namespace std;
using namespace cv;
void initBackgroundSubtractor(BackgroundSubtractorMOG2 &bSub)
{
bSub.set("detectShadows", 1);
}
Mat doBackgroundSubtract(BackgroundSubtractorMOG2 &bSub, Mat panorama)
{
Mat foreground;
bSub.operator()(panorama, foreground);
erode(foreground, foreground, Mat(), Point(-1, -1), ERODEIT, BORDER_DEFAULT);
dilate(foreground, foreground, Mat(), Point(-1, -1), DILATEIT, BORDER_DEFAULT);
return foreground;
}
// **contourOps.cpp**
/* Functions that operate on, filter, or relate to OpenCV contours vectors */
#include <opencv2/opencv.hpp>
#include <vector>
#include <fstream>
#include "defines.h"
using namespace std;
using namespace cv;
/* Returns the centroid of a contour */
Point getCentroid(vector<Point> contour)
{
Point centroid;
Moments m;
m = moments(contour, false);
centroid.x = int(m.m10/m.m00);
centroid.y = int(m.m01/m.m00);
return centroid;
}
/* Draws a rectangle around a contour */
void drawBoundingBoxes(vector<vector<Point>> contours, Mat &img)
{
vector<Rect> boundRect(contours.size());
for(unsigned int j = 0; j < contours.size(); j++)
{
boundRect[j] = boundingRect(contours[j]);
rectangle(img, boundRect[j], Scalar(153,0,76), 2, 8, 0);
}
}
/* Removes contours from a vector if they're smaller than the argument "area" */
void contourSizeTrim (vector<vector<Point>> &contours, int area)
{
vector<vector<Point>>::iterator i = contours.begin();
while(i != contours.end())
{
if(contourArea(*i, false) < area)
i = contours.erase(i);
else
i++;
}
}
/* Removes contours from a vector if they're X % smaller than largest contour in vector */
void contourRelSizeTrim(vector<vector<Point>> &contours, int percent)
{
double maxArea = 0.0;
for(unsigned int i=0; i<contours.size(); i++)
{
if (contourArea(contours[i], false) > maxArea)
maxArea = contourArea(contours[i], false);
}
vector<vector<Point>>::iterator j = contours.begin();
while(j != contours.end())
{
if (contourArea(*j, false) < (double)(percent/100.0)*maxArea)
j = contours.erase(j);
else
j++;
}
}
// **realtimestitch.cpp**
#include <opencv2/opencv.hpp>
#include <opencv2/stitching/stitcher.hpp>
#include <vector>
#include <iostream>
#include "defines.h"
using namespace std;
using namespace cv;
void initStitcher(VideoCapture &capture1, VideoCapture &capture2, Stitcher &stitch)
{
capture1.set(CV_CAP_PROP_FRAME_WIDTH, WIDTH);
capture1.set(CV_CAP_PROP_FRAME_HEIGHT, HEIGHT);
capture2.set(CV_CAP_PROP_FRAME_WIDTH, WIDTH);
capture2.set(CV_CAP_PROP_FRAME_HEIGHT, HEIGHT);
detail::OrbFeaturesFinder *featureFinder = new detail::OrbFeaturesFinder(Size(3,1), 1000, 1.5f, 4);
stitch.setFeaturesFinder (featureFinder);
}
void calcCamTransform(VideoCapture &capture1, VideoCapture &capture2, Stitcher &stitch)
{
int64 t;
Mat fr1, fr2, copy1, copy2;
vector<Mat> imgs;
capture1 >> fr1;
capture2 >> fr2;
fr1.copyTo(copy1);
fr2.copyTo(copy2);
imgs.push_back(copy1);
imgs.push_back(copy2);
stitch.estimateTransform(imgs);
}
Mat doStitch(VideoCapture &capture1, VideoCapture &capture2, Stitcher &stitch)
{
Mat fr1, fr2, copy1, copy2, panorama;
vector<Mat> imgs;
capture1 >> fr1;
capture2 >> fr2;
fr1.copyTo(copy1);
fr2.copyTo(copy2);
imgs.push_back(copy1);
imgs.push_back(copy2);
Stitcher::Status status = stitch.composePanorama(imgs, panorama);
if (status != Stitcher::OK)
cout << "Error Stitching: Code: " << int(status) << endl;
return panorama;
}
// **main.cpp**
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include "defines.h"
#include "protos.h"
using namespace cv;
int main()
{
bool doTransform = true, doSizeFilter = true, doRelSizeFilter = true;
Mat pano, fGround;
vector<vector<Point>> contours;
VideoCapture cap1(0);
VideoCapture cap2(1);
Stitcher stitcher = Stitcher::createDefault();
BackgroundSubtractorMOG2 bGround;
initStitcher(cap1, cap2, stitcher);
initBackgroundSubtractor(bGround);
while (true)
{
if (doTransform)
{
calcCamTransform(cap1, cap2, stitcher);
doTransform = !doTransform;
}
pano = doStitch(cap1, cap2, stitcher);
fGround = doBackgroundSubtract(bGround, pano);
findContours(fGround, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
if (doSizeFilter)
contourSizeTrim(contours, AREATHRESH);
if (doRelSizeFilter)
contourRelSizeTrim(contours, RELSIZEPERCENT);
drawBoundingBoxes(contours, pano);
imshow("Stitched Image", pano);
if(waitKey(1) >= 0)
break;
}
return 0;
}
This is a problem related to OpenCV and VS2012 - on VS2010, there are no problems, and the code runs perfectly!
My opinion about this is that the contour you are trying to do something with an empty vector of contours. Have you verified that? Try a
if (contours.empty()) continue; // or here you can display the image to see if it is empty or not
I had the same problem because I was trying to give an epty vector to cv::IsContourConvex(...) function (see here).