I wanted to try that
Vec3b colorsense = {
map.at<Vec3b>(trace.move_up(1)),
map.at<Vec3b>(trace.move_down(1)),
map.at<Vec3b>(trace.move_left(1)),
map.at<Vec3b>(trace.move_right(1)),
map.at<Vec3b>(trace.move_upright(1)),
map.at<Vec3b>(trace.move_upleft(1)),
map.at<Vec3b>(trace.move_downright(1)),
map.at<Vec3b>(trace.move_downleft(1))};
can be usable, but after testing it, I don
t think that it work. oh and the function trace.move_up are all points in the matrix map
This is my entire main code:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "Trace.h"
// Macros
#define log(x) std::cout << x << std::endl;
#define error(x) std::cerr << x << std::endl;
// using namespaces:
//using namespace cv;
//using namespace std;
// enum;
enum {up = 0, down = 1, left = 2, right = 3, upright = 4, upleft = 5, downright = 6, downleft = 7};
// Main function;
int main() {
try {
int x = 0,movement;
Trace trace(0, 0);
Mat map = imread("tmp.bmp"), edges;
resize(map, map, {1028, 672}, 0, 0, INTER_NEAREST_EXACT);
std::vector<Vec3b> colorsense = {
map.at<Vec3b>(trace.move_up(1)),
map.at<Vec3b>(trace.move_down(1)),
map.at<Vec3b>(trace.move_left(1)),
map.at<Vec3b>(trace.move_right(1)),
map.at<Vec3b>(trace.move_upright(1)),
map.at<Vec3b>(trace.move_upleft(1)),
map.at<Vec3b>(trace.move_downright(1)),
map.at<Vec3b>(trace.move_downleft(1))};
switch (movement) {
case up:
colorsense[up];
break;
case down:
colorsense[down];
break;
case left:
colorsense[left];
break;
case right:
colorsense[right];
break;
case upright:
colorsense[upright];
break;
case upleft:
colorsense[upleft];
break;
case downright:
colorsense[downright];
break;
case downleft:
colorsense[downleft];
break;
default:
movement = right;
break;
}
for (int i = 0; i < 1000; i++){
trace.draw(map, 255, 0, 0, 1);
if(colorsense[right][0]== 255 || colorsense[right][1]== 255 || colorsense[right][2]== 255){
trace.move_downright(0);
} else {
trace.move_right(0);
}
namedWindow("map");
imshow("map", map);
waitKey(10);
}
// Canny(map,edges,100,100,3,false);
// Laplacian(map,map, CV_64F);
log(map.rows);
log(map.cols);
if (map.empty()) {
error("Could not load image");
return EXIT_FAILURE;
}
namedWindow("map");
imshow("map", map);
waitKey();
log("Hello World");
}
catch(const char* msg){
error(msg);
}
return 0;
}
The for loop you guys see here is the loop that draws the line. But with the function i wrote, it won't be able to change direction when the black objects is close.
But when i write the if statement similar like this
map.at<Vec3b>(trace.move_up(1))[0]
map.at<Vec3b>(trace.move_up(1))[1]
map.at<Vec3b>(trace.move_up(1))[2]
Then it works..., why?
Related
I'm trying to use an "example" code for c++ on qt. In this example, there's a function "get_top_n" from tflite::label_image, in tensorflow/lite/examples/label_image/get_top_n.h. But, qt creator doesn't find the function.
Error: main.cpp:104 (and 107): erreur : no matching function for call to 'get_top_n'
What am I doing wrong here ?
#include <fstream>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/string_util.h"
#include "tensorflow/lite/examples/label_image/get_top_n.h"
#include "tensorflow/lite/model.h"
std::vector<std::string> load_labels(std::string labels_file)
{
std::ifstream file(labels_file.c_str());
if (!file.is_open())
{
fprintf(stderr, "unable to open label file\n");
exit(-1);
}
std::string label_str;
std::vector<std::string> labels;
while (std::getline(file, label_str))
{
if (label_str.size() > 0)
labels.push_back(label_str);
}
file.close();
return labels;
}
int main(int argc, char *argv[])
{
// Get Model label and input image
if (argc != 4)
{
fprintf(stderr, "TfliteClassification.exe modelfile labels image\n");
exit(-1);
}
const char *modelFileName = argv[1];
const char *labelFile = argv[2];
const char *imageFile = argv[3];
// Load Model
auto model = tflite::FlatBufferModel::BuildFromFile(modelFileName);
if (model == nullptr)
{
fprintf(stderr, "failed to load model\n");
exit(-1);
}
// Initiate Interpreter
std::unique_ptr<tflite::Interpreter> interpreter;
tflite::ops::builtin::BuiltinOpResolver resolver;
tflite::InterpreterBuilder(*model, resolver)(&interpreter);
if (interpreter == nullptr)
{
fprintf(stderr, "Failed to initiate the interpreter\n");
exit(-1);
}
if (interpreter->AllocateTensors() != kTfLiteOk)
{
fprintf(stderr, "Failed to allocate tensor\n");
exit(-1);
}
// Configure the interpreter
interpreter->SetAllowFp16PrecisionForFp32(true);
interpreter->SetNumThreads(1);
// Get Input Tensor Dimensions
int input = interpreter->inputs()[0];
auto height = interpreter->tensor(input)->dims->data[1];
auto width = interpreter->tensor(input)->dims->data[2];
auto channels = interpreter->tensor(input)->dims->data[3];
// Load Input Image
cv::Mat image;
auto frame = cv::imread(imageFile);
if (frame.empty())
{
fprintf(stderr, "Failed to load iamge\n");
exit(-1);
}
// Copy image to input tensor
cv::resize(frame, image, cv::Size(width, height), cv::INTER_NEAREST);
memcpy(interpreter->typed_input_tensor<unsigned char>(0), image.data, image.total() * image.elemSize());
// Inference
std::chrono::steady_clock::time_point start, end;
start = std::chrono::steady_clock::now();
interpreter->Invoke();
end = std::chrono::steady_clock::now();
auto inference_time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// Get Output
int output = interpreter->outputs()[0];
TfLiteIntArray *output_dims = interpreter->tensor(output)->dims;
auto output_size = output_dims->data[output_dims->size - 1];
std::vector<std::pair<float, int>> top_results;
float threshold = 0.01f;
switch (interpreter->tensor(output)->type)
{
case kTfLiteInt32:
tflite::label_image::get_top_n<float>(interpreter->typed_output_tensor<float>(0), output_size, 1, threshold, &top_results, kTfLiteFloat32);
break;
case kTfLiteUInt8:
tflite::label_image::get_top_n<uint8_t>(interpreter->typed_output_tensor<uint8_t>(0), output_size, 1, threshold, &top_results, kTfLiteUInt8);
break;
default:
fprintf(stderr, "cannot handle output type\n");
exit(-1);
}
// Print inference ms in input image
cv::putText(frame, "Infernce Time in ms: " + std::to_string(inference_time), cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar(0, 0, 255), 2);
// Load Labels
auto labels = load_labels(labelFile);
// Print labels with confidence in input image
for (const auto &result : top_results)
{
const float confidence = result.first;
const int index = result.second;
std::string output_txt = "Label :" + labels[index] + " Confidence : " + std::to_string(confidence);
cv::putText(frame, output_txt, cv::Point(10, 60), cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar(0, 0, 255), 2);
}
// Display image
cv::imshow("Output", frame);
cv::waitKey(0);
return 0;
}
The lines affected :
104: tflite::label_image::get_top_n<float>(interpreter->typed_output_tensor<float>(0), output_size, 1, threshold, &top_results, kTfLiteFloat32);
107: tflite::label_image::get_top_n<uint8_t>(interpreter->typed_output_tensor<uint8_t>(0), output_size, 1, threshold, &top_results, kTfLiteUInt8);
Content of tensorflow/lite/examples/label_image/get_top_n.h:
/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. ...*/
#ifndef TENSORFLOW_LITE_EXAMPLES_LABEL_IMAGE_GET_TOP_N_H_
#define TENSORFLOW_LITE_EXAMPLES_LABEL_IMAGE_GET_TOP_N_H_
#include "tensorflow/lite/examples/label_image/get_top_n_impl.h"
namespace tflite {
namespace label_image {
template <class T>
void get_top_n(T* prediction, int prediction_size, size_t num_results,
float threshold, std::vector<std::pair<float, int>>* top_results,
TfLiteType input_type);
// explicit instantiation so that we can use them otherwhere
template void get_top_n<float>(float*, int, size_t, float,
std::vector<std::pair<float, int>>*, TfLiteType);
template void get_top_n<int8_t>(int8_t*, int, size_t, float,
std::vector<std::pair<float, int>>*,
TfLiteType);
template void get_top_n<uint8_t>(uint8_t*, int, size_t, float,
std::vector<std::pair<float, int>>*,
TfLiteType);
} // namespace label_image
} // namespace tflite
#endif // TENSORFLOW_LITE_EXAMPLES_LABEL_IMAGE_GET_TOP_N_H_
Content of tensorflow/lite/examples/label_image/get_top_n_impl.h:
/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. ...*/
#ifndef TENSORFLOW_LITE_EXAMPLES_LABEL_IMAGE_GET_TOP_N_IMPL_H_
#define TENSORFLOW_LITE_EXAMPLES_LABEL_IMAGE_GET_TOP_N_IMPL_H_
#include <algorithm>
#include <functional>
#include <queue>
#include "tensorflow/lite/c/common.h"
namespace tflite {
namespace label_image {
extern bool input_floating;
// Returns the top N confidence values over threshold in the provided vector,
// sorted by confidence in descending order.
template <class T>
void get_top_n(T* prediction, int prediction_size, size_t num_results,
float threshold, std::vector<std::pair<float, int>>* top_results,
TfLiteType input_type) {
// Will contain top N results in ascending order.
std::priority_queue<std::pair<float, int>, std::vector<std::pair<float, int>>,
std::greater<std::pair<float, int>>>
top_result_pq;
const long count = prediction_size; // NOLINT(runtime/int)
float value = 0.0;
for (int i = 0; i < count; ++i) {
switch (input_type) {
case kTfLiteFloat32:
value = prediction[i];
break;
case kTfLiteInt8:
value = (prediction[i] + 128) / 256.0;
break;
case kTfLiteUInt8:
value = prediction[i] / 255.0;
break;
default:
break;
}
// Only add it if it beats the threshold and has a chance at being in
// the top N.
if (value < threshold) {
continue;
}
top_result_pq.push(std::pair<float, int>(value, i));
// If at capacity, kick the smallest value out.
if (top_result_pq.size() > num_results) {
top_result_pq.pop();
}
}
// Copy to output vector and reverse into descending order.
while (!top_result_pq.empty()) {
top_results->push_back(top_result_pq.top());
top_result_pq.pop();
}
std::reverse(top_results->begin(), top_results->end());
}
} // namespace label_image
} // namespace tflite
#endif // TENSORFLOW_LITE_EXAMPLES_LABEL_IMAGE_GET_TOP_N_IMPL_H_
Github link
I'd like to do an simple dnn example for getting known with mlpack.
The simple example is to train a dnn with the MNist Digits - the classical
ml-hello world case :-)
I managed to preparate all images using opencv-filters - the result is a
monochannel grayscale opencv::mat matrix.
I also managed to convert the pixle values to the armadillo matrix arma::mat
and to label this "pictures".
But somewhere in the past two operations, I did a mistake.
I got N examples and M Input Neurons
IN means "Input Neuron"
OL means "OutputLabel"
Ex means "Example"
The structure of my train-data is like that:
arma::mat TrainSet = {{IN_1/Ex_1,IN_/Ex_2,IN_1/Ex_3,...,IN_1/Ex_N},
{IN_2/Ex_1, IN_2/Ex_2, IN_2/Ex_3,...,IN_2/Ex_N},
{...},
{IN_M/Ex_1, IN_M/Ex_2, IN_M/Ex_3,...,IN_M/Ex_N}}`
arma::mat LabelSet = {OL_Ex_1, OL_Ex_2, ..., OL_Ex_N}
Training my network leeds to an error.
Error training artificial neural network!
Error details: Mat::operator(): index out of bounds
I'm quite sure, that the structure of my train- and labelstack is not correct.
Does anybody know, what I did wrong?
I tried to follow this example and to translate it to my case:
http://www.mlpack.org/docs/mlpack-git/doxygen/cnetutorial.html
Here is a picture of visual studio showing the structure of my trainset:
Here is a picture of visual studio showing the structure of my lables:
Thank you for any help.
Yours,
Jan
This is my code:
#pragma region Includings
#include <iostream>
#include <stdlib.h>
#include <exception>
#include <string>
#include "opencv2/opencv.hpp"
#include <mlpack\\core.hpp>
#include <mlpack/methods/ann/layer/layer.hpp>
#include <mlpack/methods/ann/ffn.hpp>
#include <mlpack/core/optimizers/cne/cne.hpp>
#pragma endregion
#pragma region Globals
std::string TrainFolder = "C:\\HomeC\\MNist\\MNist\\train-labels\\";
#pragma endregion
#pragma region Structs
typedef struct TInputPair {
double Value;
int Index;
};
typedef struct TDigitPairExample {
TInputPair* InputPairArray;
int nNonZero;
char OutputValue;
};
#pragma endregion
#pragma region Identifier
void DisplayImage(cv::Mat* Img, std::string Title = "CV::DefaultForm");
std::vector<TDigitPairExample> GenerateTrainingSet(std::string TrainFolder, int nExamplesPerClass, bool DisplayAtWindow = false);
void DisplayImage(cv::Mat* Img, std::string Title, int Delay = 0);
TInputPair* MatToArray(cv::Mat* img, int* nEntries);
int CharToOutputInt(char c);
void TransferDataToMLPack(std::vector<TDigitPairExample>* ExStack, arma::mat* DataStack, arma::mat* LabelStack, int nInput);
typedef uchar Pixel;
#pragma endregion
int main() {
#pragma region Get training examples from images
std::vector<TDigitPairExample> TrainExamples = GenerateTrainingSet(TrainFolder, 101);
#pragma endregion
#pragma region Convert training vector to armadillo matrix
arma::mat trainset, labels;
TransferDataToMLPack(&TrainExamples, &trainset, &labels, 784);
#pragma endregion
#pragma region Define network
mlpack::ann::FFN<mlpack::ann::NegativeLogLikelihood<> > network;
network.Add<mlpack::ann::Linear<> >(784, 784);
network.Add<mlpack::ann::SigmoidLayer<> >();
network.Add<mlpack::ann::Linear<> >(784, 10);
network.Add<mlpack::ann::LogSoftMax<> >();
#pragma endregion
#pragma region Train network
try {
network.Train(trainset, labels);
}catch (const std::exception& e) {
std::cout << "Error training artificial neural network!" << std::endl << "Error details: " << e.what() << std::endl;
}
#pragma endregion
std::cout << "Application finished. Press ENTER to exit..." << std::endl;
std::cin.get();
}
#pragma region Private_regions
void DisplayImage(cv::Mat* Img, std::string Title, int Delay) {
/***************/
/*Define window*/
/***************/
cv:cvNamedWindow(Title.c_str(), cv::WINDOW_AUTOSIZE);
cv::imshow(Title.c_str(), *Img);
cv::waitKey(Delay);
//cv::destroyWindow(Title.c_str());
return;
}
TInputPair* MatToArray(cv::Mat* img, int* nEntries) {
uchar* ptr = nullptr, *dptr = nullptr;
TInputPair* InPairArr = nullptr;
int j = 0;
if (img->isContinuous()) {
ptr = img->ptr<uchar>();
}else { return nullptr; }
InPairArr = (TInputPair*)malloc((img->cols) * (img->rows) * sizeof(TInputPair));
if (InPairArr == nullptr) { return nullptr; }
for (int i = 0; i < (img->rows)*(img->cols); i++) {
//std::cout << "Index_" + std::to_string(i) + "; " + std::to_string(ptr[i]) << std::endl;
if (ptr[i] != 255) { InPairArr[j].Index = i; InPairArr[j].Value = (double)(255 - ptr[i]) / 255.0; j++; }
}
InPairArr = (TInputPair*)realloc(InPairArr, j * sizeof(TInputPair));
*nEntries = j;
return InPairArr;
}
std::vector<TDigitPairExample> GenerateTrainingSet(std::string TrainFolder, int nExamplesPerClass, bool DisplayAtWindow) {
/********/
/*Localc*/
/********/
int nEntries = 0;
cv::Mat imgMod, imgGrad, imgInv, ptHull, imgHull, imgResize;
std::vector<std::vector<cv::Point>> contours;
std::vector<TDigitPairExample> TrainExamples;
TDigitPairExample TDPE;
for (int i = 1, j = 0;; i++) {
/**************/
/*Reading file*/
/**************/
cv::Mat imgOrig = cv::imread(TrainFolder + std::to_string(j) + "_" + std::to_string(i) + ".bmp", cv::IMREAD_GRAYSCALE);
if (imgOrig.empty() || i > 100) { j++; i = 1; if (j > 9) { break; } continue; }
/****************/
/*Build negative*/
/****************/
cv::subtract(cv::Scalar::all(255.0), imgOrig, imgMod);
/*****************/
/*Cut by treshold*/
/*****************/
cv::threshold(imgMod, imgMod, 230.0, 255.0, cv::THRESH_BINARY);
/**************/
/*Get contours*/
/**************/
//cv::findContours(imgMod, contours, cv::CHAIN_APPROX_NONE, 1);
//cv::Scalar color = cv::Scalar(255, 0, 0);
//cv::drawContours(imgMod, contours, -1, color, 1, 8);
//cv::Laplacian(imgOrig, imgGrad, 16, 1, 1.0, 0.0, cv::BORDER_REFLECT);
/********************/
/*Resize and display*/
/********************/
cv::resize(imgMod, imgResize, cv::Size(300, 300), .0, .0, cv::INTER_LINEAR);
TDPE.InputPairArray = MatToArray(&imgMod, &nEntries);
TDPE.nNonZero = nEntries;
TDPE.OutputValue = std::to_string(j).c_str()[0];
TrainExamples.push_back(TDPE);
if (DisplayAtWindow) { DisplayImage(&imgResize, std::string("After inversion"), 5); }
}
return TrainExamples;
}
int CharToOutputInt(char c) {
switch (c) {
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
default: throw new std::exception();
}
}
void TransferDataToMLPack(std::vector<TDigitPairExample>* ExStack, arma::mat* DataStack, arma::mat* LabelStack, int nInput) {
*DataStack = arma::zeros(nInput, ExStack->size());
*LabelStack = arma::zeros(1, ExStack->size()); /*...edit...*/
TDigitPairExample DPE;
TInputPair TIP;
/*Looping all digit examples*/
for (int i = 0; i < ExStack->size(); i++) {
DPE = (*ExStack)[i];
/*Looping all nonZero pixle*/
for (int j = 0; j < DPE.nNonZero; j++) {
TIP = DPE.InputPairArray[j];
try {
(*DataStack)(TIP.Index, i) = TIP.Value;
}catch (std::exception& ex) {
std::cout << "Error adding example[" << std::to_string(j) << "] to training stack!" << std::endl <<
"Error details: " << ex.what() << std::endl;
}
}
/*Adding label*/
try {
(*LabelStack)(0, i) = CharToOutputInt(DPE.OutputValue); /*...edit...*/
}catch (std::exception& ex) {
std::cout << "Error adding example[" << std::to_string(i) << "] to label stack!" << std::endl <<
"Error details: " << ex.what() << std::endl;
}
}
return;
}
#pragma endregion
The NegativeLogLikelihood loss function expects the target to be in the range [1, N], so you would have to increase the return value of CharToOutputInt. In case you haven't seen it already there is an interesting example: mlpack - DigitRecognizerCNN which could be helpful as well.
Ok, thanks to Marcus, I found the error. A label "0" is not allowed. I simply changed the lables to:
1 ==> Zero
2 ==> One
3 ==> Two
...
10 => Nine
That worked.
I am new in OpenCV world and neural networks but I have some coding experience in C++/Java.
I created my first ANN MLP and learned it the XOR:
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/ml/ml.hpp>
#include <iostream>
#include <iomanip>
using namespace cv;
using namespace ml;
using namespace std;
void print(Mat& mat, int prec)
{
for (int i = 0; i<mat.size().height; i++)
{
cout << "[";
for (int j = 0; j<mat.size().width; j++)
{
cout << fixed << setw(2) << setprecision(prec) << mat.at<float>(i, j);
if (j != mat.size().width - 1)
cout << ", ";
else
cout << "]" << endl;
}
}
}
int main()
{
const int hiddenLayerSize = 4;
float inputTrainingDataArray[4][2] = {
{ 0.0, 0.0 },
{ 0.0, 1.0 },
{ 1.0, 0.0 },
{ 1.0, 1.0 }
};
Mat inputTrainingData = Mat(4, 2, CV_32F, inputTrainingDataArray);
float outputTrainingDataArray[4][1] = {
{ 0.0 },
{ 1.0 },
{ 1.0 },
{ 0.0 }
};
Mat outputTrainingData = Mat(4, 1, CV_32F, outputTrainingDataArray);
Ptr<ANN_MLP> mlp = ANN_MLP::create();
Mat layersSize = Mat(3, 1, CV_16U);
layersSize.row(0) = Scalar(inputTrainingData.cols);
layersSize.row(1) = Scalar(hiddenLayerSize);
layersSize.row(2) = Scalar(outputTrainingData.cols);
mlp->setLayerSizes(layersSize);
mlp->setActivationFunction(ANN_MLP::ActivationFunctions::SIGMOID_SYM);
TermCriteria termCrit = TermCriteria(
TermCriteria::Type::COUNT + TermCriteria::Type::EPS,
100000000,
0.000000000000000001
);
mlp->setTermCriteria(termCrit);
mlp->setTrainMethod(ANN_MLP::TrainingMethods::BACKPROP);
Ptr<TrainData> trainingData = TrainData::create(
inputTrainingData,
SampleTypes::ROW_SAMPLE,
outputTrainingData
);
mlp->train(trainingData
/*, ANN_MLP::TrainFlags::UPDATE_WEIGHTS
+ ANN_MLP::TrainFlags::NO_INPUT_SCALE
+ ANN_MLP::TrainFlags::NO_OUTPUT_SCALE*/
);
for (int i = 0; i < inputTrainingData.rows; i++) {
Mat sample = Mat(1, inputTrainingData.cols, CV_32F, inputTrainingDataArray[i]);
Mat result;
mlp->predict(sample, result);
cout << sample << " -> ";// << result << endl;
print(result, 0);
cout << endl;
}
return 0;
}
It works very well for this simple problem, I also learn this network the 1-10 to binary conversion.
But i need to use MLP for simple image classification - road signs. I write the code for loading training images and preparing matrix for learning but I'm not able to train the network - it "learn" in one second even with 1 000 000 iterations! And it produce garbage results, the same for all inputs!
Here are my test images and the source code:
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/ml/ml.hpp>
#include <iostream>
#include <chrono>
#include <memory>
#include <iomanip>
#include <climits>
#include <Windows.h>
using namespace cv;
using namespace ml;
using namespace std;
using namespace chrono;
const int WIDTH_SIZE = 50;
const int HEIGHT_SIZE = (int)(WIDTH_SIZE * sqrt(3)) / 2;
const int IMAGE_DATA_SIZE = WIDTH_SIZE * HEIGHT_SIZE;
void print(Mat& mat, int prec)
{
for (int i = 0; i<mat.size().height; i++)
{
cout << "[ ";
for (int j = 0; j<mat.size().width; j++)
{
cout << fixed << setw(2) << setprecision(prec) << mat.at<float>(i, j);
if (j != mat.size().width - 1)
cout << ", ";
else
cout << " ]" << endl;
}
}
}
bool loadImage(string imagePath, Mat& outputImage)
{
// load image in grayscale
Mat image = imread(imagePath, IMREAD_GRAYSCALE);
Mat temp;
// check for invalid input
if (image.empty()) {
cout << "Could not open or find the image" << std::endl;
return false;
}
// resize the image
Size size(WIDTH_SIZE, HEIGHT_SIZE);
resize(image, temp, size, 0, 0, CV_INTER_AREA);
// convert to float 1-channel
temp.convertTo(outputImage, CV_32FC1, 1.0/255.0);
return true;
}
vector<string> getFilesNamesInFolder(string folder)
{
vector<string> names;
char search_path[200];
sprintf(search_path, "%s/*.*", folder.c_str());
WIN32_FIND_DATA fd;
HANDLE hFind = ::FindFirstFile(search_path, &fd);
if (hFind != INVALID_HANDLE_VALUE) {
do {
// read all (real) files in current folder
// , delete '!' read other 2 default folder . and ..
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
names.push_back(fd.cFileName);
}
} while (::FindNextFile(hFind, &fd));
::FindClose(hFind);
}
return names;
}
class Sign {
public:
enum class Category { A = 'A', B = 'B', C = 'C', D = 'D' };
Mat image;
Category category;
int number;
Sign(Mat& image, string name) :image(image) {
category = static_cast<Category>(name.at(0));
number = stoi(name.substr(2, name.length()));
};
};
vector<Sign> loadSignsFromFolder(String folderName) {
vector<Sign> roadSigns;
for (string fileName : getFilesNamesInFolder(folderName)) {
Mat image;
loadImage(folderName + fileName, image);
roadSigns.emplace_back(image, fileName.substr(0, (fileName.length() - 4))); //cut .png
}
return roadSigns;
}
void showSignsInWindows(vector<Sign> roadSigns) {
for (Sign sign : roadSigns) {
String windowName = "Sign " + to_string(sign.number);
namedWindow(windowName, WINDOW_AUTOSIZE);
imshow(windowName, sign.image);
}
waitKey(0);
}
Mat getInputDataFromSignsVector(vector<Sign> roadSigns) {
Mat roadSignsImageData;
for (Sign sign : roadSigns) {
Mat signImageDataInOneRow = sign.image.reshape(0, 1);
roadSignsImageData.push_back(signImageDataInOneRow);
}
return roadSignsImageData;
}
Mat getOutputDataFromSignsVector(vector<Sign> roadSigns) {
int signsCount = (int) roadSigns.size();
int signsVectorSize = signsCount + 1;
Mat roadSignsData(0, signsVectorSize, CV_32FC1);
int i = 1;
for (Sign sign : roadSigns) {
vector<float> outputTraningVector(signsVectorSize);
fill(outputTraningVector.begin(), outputTraningVector.end(), -1.0);
outputTraningVector[i++] = 1.0;
Mat tempMatrix(outputTraningVector, false);
roadSignsData.push_back(tempMatrix.reshape(0, 1));
}
return roadSignsData;
}
int main(int argc, char* argv[])
{
if (argc != 2) {
cout << " Usage: display_image ImageToLoadAndDisplay" << endl;
return -1;
}
const int hiddenLayerSize = 500;
vector<Sign> roadSigns = loadSignsFromFolder("../../../Znaki/A/");
Mat inputTrainingData = getInputDataFromSignsVector(roadSigns);
Mat outputTrainingData = getOutputDataFromSignsVector(roadSigns);
Ptr<ANN_MLP> mlp = ANN_MLP::create();
Mat layersSize = Mat(3, 1, CV_16U);
layersSize.row(0) = Scalar(inputTrainingData.cols);
layersSize.row(1) = Scalar(hiddenLayerSize);
layersSize.row(2) = Scalar(outputTrainingData.cols);
mlp->setLayerSizes(layersSize);
mlp->setActivationFunction(ANN_MLP::ActivationFunctions::SIGMOID_SYM, 1.0, 1.0);
mlp->setTrainMethod(ANN_MLP::TrainingMethods::BACKPROP, 0.05, 0.05);
//mlp->setTrainMethod(ANN_MLP::TrainingMethods::RPROP);
TermCriteria termCrit = TermCriteria(
TermCriteria::Type::MAX_ITER //| TermCriteria::Type::EPS,
,100 //(int) INT_MAX
,0.000001
);
mlp->setTermCriteria(termCrit);
Ptr<TrainData> trainingData = TrainData::create(
inputTrainingData,
SampleTypes::ROW_SAMPLE,
outputTrainingData
);
auto start = system_clock::now();
mlp->train(trainingData
//, //ANN_MLP::TrainFlags::UPDATE_WEIGHTS
, ANN_MLP::TrainFlags::NO_INPUT_SCALE
+ ANN_MLP::TrainFlags::NO_OUTPUT_SCALE
);
auto duration = duration_cast<milliseconds> (system_clock::now() - start);
cout << "Training time: " << duration.count() << "ms" << endl;
for (int i = 0; i < inputTrainingData.rows; i++) {
Mat result;
//mlp->predict(inputTrainingData.row(i), result);
mlp->predict(roadSigns[i].image.reshape(0, 1), result);
//cout << result << endl;
print(result, 2);
}
//showSignsInWindows(roadSigns);
return 0;
}
What is wrong in this code, that XOR works but images not? I cheked the input and output matrix and they're correct... could somebody also explain me when to/shoud I use the ANN_MLP::TrainFlags::NO_INPUT_SCALE and ANN_MLP::TrainFlags::NO_OUTPUT_SCALE or what values of setActivationFunction and setTrainMethod parameters should I use?
Thanks!
There was a problem in backprop weight scale parameter - it was too big and the ANN couldn't learn more difficult things.
I changed the line to mlp->setTrainMethod(ANN_MLP::TrainingMethods::BACKPROP, 0.0001); and the hidden layer size to 100 (to speed up the learning) - now it's working!
I am working on an Image Processing toolbox, that links OpenCV to Scilab, so that OpenCV functions can be used in Scilab directly. Now, my issue is that I have many functions that are used in all the other codes, so i decided to include those in an external cpp file, and include that in my other codes. What I did was, i made a header file common.h with the function definitions. common.c has the actual functions written. And all my other files, for e.g opencv_imcrop have a #include "common.h" along with the other included header files. However, when i compile this in Scilab using my builder gateway file(a .sce file that compiles my opencv_imcrop.cpp), it gives the following error:-
opencv_imcrop.cpp:14:22: fatal error: common.h: No such file or directory
compilation terminated.
This is my common.h file:-
#include "common.cpp"
string type2str(int type);
int no_of_channels(int type);
int retrieveImage(Mat &image);
int returnImage(char *checker,int &temp,Mat img);
This is my common.cpp file:-
string type2str(int type)
{
string r;
uchar depth = type & CV_MAT_DEPTH_MASK;
switch ( depth )
{
case CV_8U: r = "8U"; break;
case CV_8S: r = "8S"; break;
case CV_16U: r = "16U"; break;
case CV_16S: r = "16S"; break;
case CV_32S: r = "32S"; break;
case CV_32F: r = "32F"; break;
case CV_64F: r = "64F"; break;
default: r = "User"; break;
}
return r;
}
int no_of_channels(int type)
{
uchar chans = 1 + (type >> CV_CN_SHIFT);
return chans;
}
//Note : the other 2 functions are also present here, but they
// comprise of 800 lines of code, so i did not paste them here
My opencv_imcrop.cpp(The file that has to include the above made header file to use the functions) file is:-
#include <numeric>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
extern "C"
{
#include "api_scilab.h"
#include "Scierror.h"
#include "BOOL.h"
#include <localization.h>
#include "common.h"
int opencv_imcrop(char *fname, unsigned long fname_len)
{
SciErr sciErr;
int iRows=0,iCols=0;
int *piAddr = NULL;
int *piAddrNew = NULL;
int *piAddr2 = NULL;
int *piAddr3 = NULL;
int *piAddr4 = NULL;
int *piAddr5 = NULL;
unsigned char *pstDataR = NULL;
unsigned char *pstDataG = NULL;
unsigned char *pstDataB = NULL;
int i,j,k;
double *x,*y,*width,*height;
//checking input argument
CheckInputArgument(pvApiCtx, 5, 5);
CheckOutputArgument(pvApiCtx, 1, 1) ;
Mat image;
retrieveImage(image);
//for value of top-left x-coordinate
sciErr = getVarAddressFromPosition(pvApiCtx,2,&piAddr2);
if (sciErr.iErr)
{
printError(&sciErr, 0);
return 0;
}
sciErr = getMatrixOfDouble(pvApiCtx, piAddr2, &iRows, &iCols ,&x);
if(sciErr.iErr)
{
printError(&sciErr, 0);
return 0;
}
//for value top-left y-coordinate
sciErr = getVarAddressFromPosition(pvApiCtx,3,&piAddr3);
if (sciErr.iErr)
{
printError(&sciErr, 0);
return 0;
}
sciErr = getMatrixOfDouble(pvApiCtx, piAddr3, &iRows, &iCols ,&y);
if(sciErr.iErr)
{
printError(&sciErr, 0);
return 0;
}
//for value of width
sciErr = getVarAddressFromPosition(pvApiCtx,4,&piAddr4);
if (sciErr.iErr)
{
printError(&sciErr, 0);
return 0;
}
sciErr = getMatrixOfDouble(pvApiCtx, piAddr4, &iRows, &iCols ,&width);
if(sciErr.iErr)
{
printError(&sciErr, 0);
return 0;
}
//for value of height
sciErr = getVarAddressFromPosition(pvApiCtx,5,&piAddr5);
if (sciErr.iErr)
{
printError(&sciErr, 0);
return 0;
}
sciErr = getMatrixOfDouble(pvApiCtx, piAddr5, &iRows, &iCols ,&height);
if(sciErr.iErr)
{
printError(&sciErr, 0);
return 0;
}
//defining a temporary rectangle, that denotes the area that has to be cropped into the new image
Rect myROI(x[0], y[0], width[0], height[0]);
// Crop the full image to that image contained by the rectangle myROI
// Note that this doesn't copy the data
Mat croppedRef(image, myROI);
Mat cropped;
// Copy the data into new matrix
croppedRef.copyTo(cropped);
int temp = nbInputArgument(pvApiCtx) + 1;
string tempstring = type2str(cropped.type());
char *checker;
checker = (char *)malloc(tempstring.size() + 1);
memcpy(checker, tempstring.c_str(), tempstring.size() + 1);
returnImage(checker,temp,cropped);
//Assigning the list as the Output Variable
AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1;
//Returning the Output Variables as arguments to the Scilab environment
ReturnArguments(pvApiCtx);
return 0;
}
/* ==================================================================== */
}
And finally, the .sce(builder_gateway_cpp.sce) file i execute in scilab to compile the above cpp file is as follows:-
function builder_gw_cpp()
WITHOUT_AUTO_PUTLHSVAR = %t;
tbx_build_gateway("skeleton_cpp69690", ..
["imcrop","opencv_imcrop"], ..
["opencv_imcrop.cpp"], ..
get_absolute_file_path("builder_gateway_cpp.sce"),[],"g++ -ggdb
`pkg-config --cflags opencv` -o `basename opencv_imcrop.cpp .cpp`
opencv_imcrop.cpp `pkg-config --libs opencv`");
endfunction
builder_gw_cpp();
clear builder_gw_cpp; // remove builder_gw_cpp on stack
i have the following code. i used it after applying connected components code i have the wanted results from connected components but i'm trying using the following code to remove the very small or very high labels based on a threshold.but every time i debug it i have exception.. so could anybode help me please
this is the connected components code
#include <stdio.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
#define PIXEL(img,x,y) (img)->imageData[(x)*img->widthStep+(y)]
#include <iostream>
int main()
{
IplImage *GrayImg,*outImg;
GrayImg=cvLoadImage("Gray_Image.jpg",0);
if(!GrayImg){
printf("Could not load image file: %s\n");
cvWaitKey(0);
exit(0);
}
cvThreshold(GrayImg, GrayImg, 180, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);//converting image to binary
int height,width,channels;
height = GrayImg->height;
width = GrayImg->width;
channels = GrayImg->nChannels;
printf("Processing a %dx%d image with %d channels \n",height,width,channels);
outImg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
cvZero(outImg);
//cvCopyImage(GrayImg,OutImg);
int i,j,v;
int top,left;
int topL,leftL;
int label=0;
int eq[10000][2];
int eqlength = 1;
cvNamedWindow("Gray", CV_WINDOW_AUTOSIZE);
cvShowImage("Gray", GrayImg );
for (i=0;i<height;i++) {
for (j=0;j<width;j++) {
v = (unsigned char) PIXEL(GrayImg,i,j);// cvGet2D(GrayImg,i,j).val[0];
//unsigned char v1 = PIXEL(GrayImg,i,j);
//int v2 = PIXEL(GrayImg,i,j);
//int v3 = v1;
if (v==255) {
if (i>0) top = cvGet2D(GrayImg,i-1,j).val[0];
else top = 0;
if (j>0) left = cvGet2D(GrayImg,i,j-1).val[0] ;
else left=0;
if (top==0 && left==0)
{
PIXEL(outImg,i,j) = label;
label+=1;
}
else if (top==255 && left==0) {
PIXEL(outImg,i,j) = PIXEL(outImg,i-1,j);
}
else if (top==0 && left==255) {
PIXEL(outImg,i,j) = PIXEL(outImg,i,j-1);
}
else if (top==255 && left==255) {
PIXEL(outImg,i,j) = PIXEL(outImg,i,j-1);
if (PIXEL(outImg,i-1,j) != PIXEL(outImg,i,j-1)){
if (eq[eqlength-1][0] == PIXEL(outImg,i-1,j) && eq[eqlength-1][1] == PIXEL(outImg,i,j-1)) ;
else
{
eq[eqlength][0] = PIXEL(outImg,i-1,j);
eq[eqlength][1] = PIXEL(outImg,i,j-1);
eqlength++;
}
}
}
}
}
//cvWaitKey(0);
//cvShowImage("Out", outImg);
}
int e;
for (i=0;i<height;i++)
for (j=0;j<width;j++)
if (PIXEL(outImg,i,j)!=0)
for (e=1;e<eqlength;e++)
if (PIXEL(outImg,i,j)==eq[e][0])
PIXEL(outImg,i,j)=eq[e][1];
cvNamedWindow("Out", CV_WINDOW_AUTOSIZE);
cvShowImage("Out", outImg);
and this is the code i added to remove unwanted labels
int* arr = new int [N];
//cout<<endl<<arr[0];
for (i=0;i<height;i++)
{
for (j=0;j<width;j++)
{
id=(unsigned char)PIXEL(outImg,i,j);
arr[id]++;
}
}
for (i=0;i<=N;i++)
{
if (arr[i]<5 || arr[i]>50)
arr[i]=0;
}
for (i=0;i<outImg->height;i++)
{
for (j=0;j<outImg->width;j++)
{
id=(unsigned char)PIXEL(outImg,i,j);
//id=cvGet2D(outImg,i,j).val[0];
if (arr[id]==0)
PIXEL(outImg,i,j)=0;
else
PIXEL(outImg,i,j)=255;
}
}
delete [] arr;
cvNamedWindow("CC", CV_WINDOW_AUTOSIZE);
cvShowImage("CC", outImg);
cvWaitKey(0);
/* Free memory and get out */
cvDestroyWindow("Gray");
cvReleaseImage(&GrayImg);
return 0;
}
You are exceeding the bounds of your array arr. Indexes are 0 based in C++ so when allocating an array of size N your maximum index is N-1.
int* arr = new int [N];
...
for (i=0;i<=N;i++) // Accessing element N of arr which does not exist. Use '<'
{
if (arr[i]<5 || arr[i]>50)
arr[i]=0;
}