OpenCV Number OCR - Image progressing (Filterin) - c++

I success fully cleaned image but there is problem when I clean it with inRange I got error on cvtColor here is my code:
// generate_data.cpp
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/ml/ml.hpp>
#include <iostream>
#include <vector>
// global variables ///////////////////////////////////////////////////////////////////////////////
const int MIN_CONTOUR_AREA = 20;
const int MAX_CONTOUR_AREA = 75;
const int RESIZED_IMAGE_WIDTH = 20;
const int RESIZED_IMAGE_HEIGHT = 30;
///////////////////////////////////////////////////////////////////////////////////////////////////
using namespace std;
using namespace cv;
Mat redFilter(const Mat& src)
{
assert(src.type() == CV_8UC3);
Mat redOnly;
inRange(src, Scalar(0, 0, 0), Scalar(0, 0, 0), redOnly);
return redOnly;
}
int main() {
cv::Mat matTrainingNumbers; // input image
cv::Mat matGrayscale; //
cv::Mat matBlurred; // declare various images
cv::Mat matThresh; //
cv::Mat matThreshCopy; //
std::vector<std::vector<cv::Point> > ptContours; // declare contours vector
std::vector<cv::Vec4i> v4iHierarchy; // declare contours hierarchy
cv::Mat matClassificationInts; // these are our training classifications, note we will have to perform some conversions before writing to file later
// these are our training images, due to the data types that the KNN object KNearest requires,
cv::Mat matTrainingImages; // we have to declare a single Mat, then append to it as though it's a vector,
// also we will have to perform some conversions before writing to file later
// possible chars we are interested in are digits 0 through 9, put these in vector intValidChars
std::vector<int> intValidChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
matTrainingNumbers = cv::imread("training_numbers.png"); // read in training numbers image
if (matTrainingNumbers.empty()) { // if unable to open image
std::cout << "error: image not read from file\n\n"; // show error message on command line
return(0); // and exit program
}
matTrainingNumbers = cv::Scalar::all(255) - matTrainingNumbers; // tranfsorm to inverse
matTrainingNumbers = redFilter(matTrainingNumbers); // Convert all colors to black
matTrainingNumbers = cv::Scalar::all(255) - matTrainingNumbers; // tranfsorm to inverse
cv::imshow("Cleared numbers", matTrainingNumbers);
cv::cvtColor(matTrainingNumbers, matGrayscale, CV_BGR2GRAY); // convert to grayscale - problem is here
Rest of the code is so long so I dont paste it if any one wants it I can add.
Here images that im progressing
TO:
Finally error is:assertion failed (scn == 3 scn == 4) in cvtcolor

Just read the error, please.
According to the docs:
C++: void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst)
...
Parameters:
...
dst – output array of the same size as src and CV_8U type.
Your dst image is single-channel. cvtColor with CV_BGR2GRAY expects a BGR image as input.

Related

Haarcascading XML does not work properly

I'm pretty new to OpenCV and cascade training. I did train a cascade to recognize "running" motion. I used Haar-like and LBP. For haar-like I used 1181 positive images and 3866 negative images and 12 stages. For LBP I used 2426 positive images and 1031 negative images and 12 staged.
Following, you could see a screenshot of each one.
After a while waiting for training to be finished (around 3-4 hours for each one) I would be able to create the xml files from AdaBoost chart classifiers.
The problem is that when I use them on my code to see how they are working, they don't recognize any of obvious running motions! The code is written with C++ and OpenCV 3.3.
Does anyone have any idea why my cascade xml files after training do not working properly?
C++ code is as below:
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/imgproc.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
//open from file
VideoCapture video("../data/videos/people_activity/run/run2.mp4");
Mat img;
Mat frmg;
// Load cascate classifier placed in sulution folder
CascadeClassifier bodydetector, rundetector;
string bodycascadeName = "haarcascade_fullbody.xml";
string runcascadeName = "lbpcascade_run.xml";
bool bodyloaded = bodydetector.load(bodycascadeName);
bool runloaded = rundetector.load(runcascadeName);
// Parameters of detectMultiscale Cascade Classifier
int groundThreshold = 1;
double scaleStep = 1.1;
Size minimalObjectSize(40, 40);
Size maximalObjectSize(200, 200);
// Vector of returned bodies and run
std::vector<Rect> bodyfound, runmotion;
while (video.read(img))
{
// Image from video read and store to Mat
video >> img;
if (img.rows == 0)//end of video
break;
// Convert input to greyscale
Mat image_grey;
cvtColor(img, image_grey, CV_BGR2GRAY);
bodyfound.clear();
// Detect bodies
bodydetector.detectMultiScale(image_grey, bodyfound, scaleStep, groundThreshold, 0 | 2, minimalObjectSize, maximalObjectSize);
for (size_t k = 0; k < bodyfound.size(); k++)
{
//draw a rectangle with red color around it
rectangle(img, bodyfound[k].br(), bodyfound[k].tl(), Scalar(0, 0, 0), 1, 8, 0);
Mat bodyROI = img(bodyfound[k]);
//Detect running for bodies if there is any!
rundetector.detectMultiScale(bodyROI, runmotion, scaleStep, groundThreshold, 0 | 2, minimalObjectSize, maximalObjectSize);
//if any were found!
if (runmotion.size() > 0) {
for (size_t i = 0; i < runmotion.size(); i++)
{
//draw a rectangle with red color around it
rectangle(img, runmotion[i].br(), runmotion[i].tl(), Scalar(80, 0, 255), 1, 8, 0);
}
}
}
imshow("result", img);
int c = waitKey(10);
if ((char)c == 27) { break; } // escape
}
return 0;
}

Blurring images of an image pyramid - Vector subscript out of range

I am trying to load an image, calculate the image pyramid (save every image) and then blur every single image of the pyramid with opencv 3.2 in C++. When I run my program I receive the error:
vector Line:1740 Expression: vector subscript out of range
Here is my code:
#include "stdafx.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>
#include <opencv2/shape/shape.hpp>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
int main(int argc, char** argv)
{
// Read the image
Mat img_1;
img_1 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
// Build an image pyramid and save it in a vector of Mat
vector<Mat> img_1_pyramid;
int pyramid_octaves = 3;
buildPyramid(img_1, img_1_pyramid, pyramid_octaves);
/* void cv::buildPyramid (InputArray src, OutputArrayOfArrays dst, int
maxlevel, int borderType = BORDER_DEFAULT) */
// Initialize parameters for the first image pyramid
vector<Mat> reduced_noise_1;
blur(img_1_pyramid[0], reduced_noise_1[0], Size(3,3));
/* void cv::blur (InputArray src, OutputArray dst, Size ksize, Point
anchor=Point(-1,-1), int borderType=BORDER_DEFAULT)*/
return 0;
}
I also tried it with a Mat object: Mat reduced_noise_1; or a vector of predefined size vector<Mat> reduced_noise(4);and I can draw img_1_pyramid[0] with imshow and receive the right image...
When I debug the program I receive an error in Line 621 of cvstd.hpp:
String::String(const char* s)
: cstr_(0), len_(0)
{
if (!s) return;
size_t len = strlen(s); // Here appears the error (only in German;))
memcpy(allocate(len), s, len);
}

Unable to detect ArUco markers with OpenCV 3.1.0

I am trying to code a simple C++ routine to first write a predefined dictionary of ArUco markers (e.g. 4x4_100) to a folder and then detect ArUco markers in a specific image selected from the folder using OpenCV 3.1 and Visual Studio 2017. I have compiled all the OpenCV-contrib libraries required to use ArUco markers. My routine builds without any error, but I am having trouble detecting the markers even after supplying all the correct arguments (e.g. image, Dictionary, etc.) to the in-built "aruco::detectMarkers" function. Could you please help me understand what`s wrong with my approach? Below is a minimal working example and the test image is attached here "4x4Marker_40.jpg":
#include "opencv2\core.hpp"
#include "opencv2\imgproc.hpp"
#include "opencv2\imgcodecs.hpp"
#include "opencv2\aruco.hpp"
#include "opencv2\highgui.hpp"
#include <sstream>
#include <fstream>
#include <iostream>
using namespace cv;
using namespace std;
// Function to write ArUco markers
void createArucoMarkers()
{
// Define variable to store the output markers
Mat outputMarker;
// Choose a predefined Dictionary of markers
Ptr< aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
// Write each of the markers to a '.jpg' image file
for (int i = 0; i < 50; i++)
{
aruco::drawMarker(markerDictionary, i, 500, outputMarker, 1);
ostringstream convert;
string imageName = "4x4Marker_";
convert << imageName << i << ".jpg";
imwrite(convert.str(), outputMarker);
}
}
// Main body of the routine
int main(int argv, char** argc)
{
createArucoMarkers();
// Read a specific image
Mat frame = imread("4x4Marker_40.jpg", CV_LOAD_IMAGE_UNCHANGED);
// Define variables to store the output of marker detection
vector<int> markerIds;
vector<vector<Point2f>> markerCorners, rejectedCandidates;
// Define a Dictionary type variable for marker detection
Ptr<aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
// Detect markers
aruco::detectMarkers(frame, markerDictionary, markerCorners, markerIds);
// Display the image
namedWindow("Webcam", CV_WINDOW_AUTOSIZE);
imshow("Webcam", frame);
// Draw detected markers on the displayed image
aruco::drawDetectedMarkers(frame, markerCorners, markerIds);
cout << "\nmarker ID is:\t"<<markerIds.size();
waitKey();
}
There are a few problems in your code:
You are displaying the image with imshow before calling drawDetectedMarkers so you'll never see the detected marker.
You are displaying the size of the markerIds vector instead of the value contained within it.
(This is the main problem) Your marker has no white space around it so it's impossible to detect.
One suggestion: use forward slashes, not backslashes in your #include statements. Forward slashes work everywhere, backslashes only work on Windows.
This worked on my machine. Note that I loaded the image as a color image to make it easier to see the results of drawDetectedMarkers.
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/aruco.hpp>
#include <opencv2/highgui.hpp>
#include <sstream>
#include <fstream>
#include <iostream>
using namespace cv;
using namespace std;
// Function to write ArUco markers
void createArucoMarkers()
{
// Create image to hold the marker plus surrounding white space
Mat outputImage(700, 700, CV_8UC1);
// Fill the image with white
outputImage = Scalar(255);
// Define an ROI to write the marker into
Rect markerRect(100, 100, 500, 500);
Mat outputMarker(outputImage, markerRect);
// Choose a predefined Dictionary of markers
Ptr< aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
// Write each of the markers to a '.jpg' image file
for (int i = 0; i < 50; i++)
{
//Draw the marker into the ROI
aruco::drawMarker(markerDictionary, i, 500, outputMarker, 1);
ostringstream convert;
string imageName = "4x4Marker_";
convert << imageName << i << ".jpg";
// Note we are writing outputImage, not outputMarker
imwrite(convert.str(), outputImage);
}
}
// Main body of the routine
int main(int argv, char** argc)
{
createArucoMarkers();
// Read a specific image
Mat frame = imread("4x4Marker_40.jpg", CV_LOAD_IMAGE_COLOR);
// Define variables to store the output of marker detection
vector<int> markerIds;
vector<vector<Point2f>> markerCorners, rejectedCandidates;
// Define a Dictionary type variable for marker detection
Ptr<aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
// Detect markers
aruco::detectMarkers(frame, markerDictionary, markerCorners, markerIds);
// Display the image
namedWindow("Webcam", CV_WINDOW_AUTOSIZE);
// Draw detected markers on the displayed image
aruco::drawDetectedMarkers(frame, markerCorners, markerIds);
// Show the image with the detected marker
imshow("Webcam", frame);
// If a marker was identified, show its ID
if (markerIds.size() > 0) {
cout << "\nmarker ID is:\t" << markerIds[0] << endl;
}
waitKey(0);
}

OpenCV SIFT key points extraction isuue

I tried to extract SIFT key points. It is working fine for a sample image I downloaded (height 400px width 247px horizontal and vertical resolutions 300dpi). Below image shows the extracted points.
Then I tried to apply the same code to a image that was taken and edited by me (height 443px width 541px horizontal and vertical resolutions 72dpi).
To create the above image I rotated the original image then removed its background and resized it using Photoshop, but my code, for that image doesn't extract features like in the first image.
See the result :
It just extract very few points. I expect a result as in the first case.
For the second case when I'm using the original image without any edit the program gives points as the first case.
Here is the simple code I have used
#include<opencv\cv.h>
#include<opencv\highgui.h>
#include<opencv2\nonfree\nonfree.hpp>
using namespace cv;
int main(){
Mat src, descriptors,dest;
vector<KeyPoint> keypoints;
src = imread(". . .");
cvtColor(src, src, CV_BGR2GRAY);
SIFT sift;
sift(src, src, keypoints, descriptors, false);
drawKeypoints(src, keypoints, dest);
imshow("Sift", dest);
cvWaitKey(0);
return 0;
}
What I'm doing wrong here? what do I need to do to get a result like in the first case to my own image after resizing ?
Thank you!
Try set nfeatures parameter (may be other parameters also need adjustment) in SIFT constructor.
Here is constructor definition from reference:
SIFT::SIFT(int nfeatures=0, int nOctaveLayers=3, double contrastThreshold=0.04, double edgeThreshold=10, double sigma=1.6)
Your code will be:
#include<opencv\cv.h>
#include<opencv\highgui.h>
#include<opencv2\nonfree\nonfree.hpp>
using namespace cv;
using namespace std;
int main(){
Mat src, descriptors,dest;
vector<KeyPoint> keypoints;
src = imread("D:\\ImagesForTest\\leaf.jpg");
cvtColor(src, src, CV_BGR2GRAY);
SIFT sift(2000,3,0.004);
sift(src, src, keypoints, descriptors, false);
drawKeypoints(src, keypoints, dest);
imshow("Sift", dest);
cvWaitKey(0);
return 0;
}
The result:
Dense sampling example:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include "opencv2/nonfree/nonfree.hpp"
int main(int argc, char* argv[])
{
cv::initModule_nonfree();
cv::namedWindow("result");
cv::Mat bgr_img = cv::imread("D:\\ImagesForTest\\lena.jpg");
if (bgr_img.empty())
{
exit(EXIT_FAILURE);
}
cv::Mat gray_img;
cv::cvtColor(bgr_img, gray_img, cv::COLOR_BGR2GRAY);
cv::normalize(gray_img, gray_img, 0, 255, cv::NORM_MINMAX);
cv::DenseFeatureDetector detector(12.0f, 1, 0.1f, 10);
std::vector<cv::KeyPoint> keypoints;
detector.detect(gray_img, keypoints);
std::vector<cv::KeyPoint>::iterator itk;
for (itk = keypoints.begin(); itk != keypoints.end(); ++itk)
{
std::cout << itk->pt << std::endl;
cv::circle(bgr_img, itk->pt, itk->size, cv::Scalar(0,255,255), 1, CV_AA);
cv::circle(bgr_img, itk->pt, 1, cv::Scalar(0,255,0), -1);
}
cv::Ptr<cv::DescriptorExtractor> descriptorExtractor = cv::DescriptorExtractor::create("SURF");
cv::Mat descriptors;
descriptorExtractor->compute( gray_img, keypoints, descriptors);
// SIFT returns large negative values when it goes off the edge of the image.
descriptors.setTo(0, descriptors<0);
imshow("result",bgr_img);
cv::waitKey();
return 0;
}
The result:

Use OpenCV Threshold with Kinect Image

I'm trying to use the OpenCV Threshold with the depthImage retrieved by the OpenCV VideoCapture module, but I get the following error:
OpenCV Error: Bad argument in unknown function,
file PATHTOOPENCV\opencv\modules\core\src\matrix.cpp line 646
My code is as follows:
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/gpu/gpu.hpp"
cv::VideoCapture kinect;
cv::Mat rgbMap;
cv::Mat dispMap;
bool newFrame;
void setup()
{
kinect.open(CV_CAP_OPENNI);
newFrame = false;
}
void update()
{
if(kinect.grab())
{
kinect.retrieve( rgbMap, CV_CAP_OPENNI_BGR_IMAGE);
kinect.retrieve( dispMap, CV_CAP_OPENNI_DISPARITY_MAP );
newFrame = true;
}
}
void draw()
{
if(newFrame)
{
cv::Mat * _thresSrc = new cv::Mat(dispMap);
cv::Mat * _thresDst = new cv::Mat(dispMap);
cvThreshold(_thresSrc, _thresDst, 24, 255, CV_THRESH_BINARY);
// Draw _thresDst;
delete _thresSrc;
delete _thresDst;
newFrame = false;
}
}
Thank you very much for your help
To start things off, you are mixing the C interface with the C++ interface, and they shouldn't be mixed together!
cv::Mat belongs to the C++ interface, and cvThreshold() belongs to the C. You should use cv::threshold() instead:
double cv::threshold(const Mat& src, Mat& dst, double thresh, double maxVal, int thresholdType)
Parameters:
src – Source array (single-channel, 8-bit of 32-bit floating point)
dst – Destination array; will have the same size and the same type as src
thresh – Threshold value
maxVal – Maximum value to use with THRESH_BINARY and THRESH_BINARY_INV thresholding types
thresholdType – Thresholding type (see the discussion)