Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何获取我的C++;检测Ñ;_C++_Opencv_Ocr - Fatal编程技术网

C++ 如何获取我的C++;检测Ñ;

C++ 如何获取我的C++;检测Ñ;,c++,opencv,ocr,C++,Opencv,Ocr,我正在做一个OCR项目,我正处于培训阶段,因此我的程序的目标是将字符检测为图像中的对象,并允许对其进行分类。 问题是,我不能用ñ得到它,因为它是由两个对象(N和棍子)组成的 你知道有没有办法把它归类为一个物体 节目如下: #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<o

我正在做一个OCR项目,我正处于培训阶段,因此我的程序的目标是将字符检测为图像中的对象,并允许对其进行分类。 问题是,我不能用ñ得到它,因为它是由两个对象(N和棍子)组成的

你知道有没有办法把它归类为一个物体

节目如下:

#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 = 30;

const int RESIZED_IMAGE_WIDTH = 20;
const int RESIZED_IMAGE_HEIGHT = 30;


 //////////////////////////////////////
int main() {

    cv::Mat imgTrainingNumbers;         // input image
    cv::Mat imgGrayscale;               // 
    cv::Mat imgBlurred;                 // declare various images
    cv::Mat imgThresh;                  //
    cv::Mat imgThreshCopy;              //

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, 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
cv::Mat matTrainingImagesAsFlattenedFloats;

// possible chars we are interested in are digits 0 through 9 and capital letters A through Z, put these in vector intValidChars
std::vector<int> intValidChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                                   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
                                   'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 
                                   'U', 'V', 'W', 'X', 'Y', 'Z'};

imgTrainingNumbers = cv::imread("caracteres_prueba.png");          // read in training numbers image

if (imgTrainingNumbers.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
}

cv::cvtColor(imgTrainingNumbers, imgGrayscale, CV_BGR2GRAY);        // convert to grayscale

cv::GaussianBlur(imgGrayscale,              // input image
    imgBlurred,                             // output image
    cv::Size(5, 5),                         // smoothing window width and height in pixels
    0);                                     // sigma value, determines how much the image will be blurred, zero makes function choose the sigma value

// filter image from grayscale to black and white
cv::adaptiveThreshold(imgBlurred,           // input image
    imgThresh,                              // output image
    255,                                    // make pixels that pass the threshold full white
    cv::ADAPTIVE_THRESH_GAUSSIAN_C,         // use gaussian rather than mean, seems to give better results
    cv::THRESH_BINARY_INV,                  // invert so foreground will be white, background will be black
    11,                                     // size of a pixel neighborhood used to calculate threshold value
    2);                                     // constant subtracted from the mean or weighted mean

cv::imshow("imgThresh", imgThresh);         // show threshold image for reference

imgThreshCopy = imgThresh.clone();          // make a copy of the thresh image, this in necessary b/c findContours modifies the image

cv::findContours(imgThreshCopy,             // input image, make sure to use a copy since the function will modify this image in the course of finding contours
    ptContours,                             // output contours
    v4iHierarchy,                           // output hierarchy
    cv::RETR_EXTERNAL,                      // retrieve the outermost contours only
    cv::CHAIN_APPROX_SIMPLE);               // compress horizontal, vertical, and diagonal segments and leave only their end points

for (int i = 0; i < ptContours.size(); i++) {                           // for each contour
    if (cv::contourArea(ptContours[i]) > MIN_CONTOUR_AREA) {                // if contour is big enough to consider
        cv::Rect boundingRect = cv::boundingRect(ptContours[i]);                // get the bounding rect

        cv::rectangle(imgTrainingNumbers, boundingRect, cv::Scalar(0, 0, 255), 2);      // draw red rectangle around each contour as we ask user for input

        cv::Mat matROI = imgThresh(boundingRect);           // get ROI image of bounding rect

        cv::Mat matROIResized;
        cv::resize(matROI, matROIResized, cv::Size(RESIZED_IMAGE_WIDTH, RESIZED_IMAGE_HEIGHT));     // resize image, this will be more consistent for recognition and storage

        cv::imshow("matROI", matROI);                               // show ROI image for reference
        cv::imshow("matROIResized", matROIResized);                 // show resized ROI image for reference
        cv::imshow("imgTrainingNumbers", imgTrainingNumbers);       // show training numbers image, this will now have red rectangles drawn on it

        int intChar = cv::waitKey(0);           // get key press

        if (intChar == 27) {        // if esc key was pressed
            return(0);              // exit program
        }
        else if (std::find(intValidChars.begin(), intValidChars.end(), intChar) != intValidChars.end()) {     // else if the char is in the list of chars we are looking for . . .

            matClassificationInts.push_back(intChar);       // append classification char to integer list of chars

            cv::Mat matImageFloat;                          // now add the training image (some conversion is necessary first) . . .
            matROIResized.convertTo(matImageFloat, CV_32FC1);       // convert Mat to float

            cv::Mat matImageFlattenedFloat = matImageFloat.reshape(1, 1);       // flatten

            matTrainingImagesAsFlattenedFloats.push_back(matImageFlattenedFloat);       // add to Mat as though it was a vector, this is necessary due to the
            // data types that KNearest.train accepts
        }   // end if
    }   // end if
}   // end for

std::cout << "training complete\n\n";

// save classifications to file ///////////////////////////////////////////////////////

cv::FileStorage fsClassifications("classifications.xml", cv::FileStorage::WRITE);           // open the classifications file

if (fsClassifications.isOpened() == false) {                                                        // if the file was not opened successfully
    std::cout << "error, unable to open training classifications file, exiting program\n\n";        // show error message
    return(0);                                                                                      // and exit program
}

fsClassifications << "classifications" << matClassificationInts;        // write classifications into classifications section of classifications file
fsClassifications.release();                                            // close the classifications file

// save training images to file ///////////////////////////////////////////////////////

cv::FileStorage fsTrainingImages("images.xml", cv::FileStorage::WRITE);         // open the training images file

if (fsTrainingImages.isOpened() == false) {                                                 // if the file was not opened successfully
    std::cout << "error, unable to open training images file, exiting program\n\n";         // show error message
    return(0);                                                                              // and exit program
}

fsTrainingImages << "images" << matTrainingImagesAsFlattenedFloats;         // write training images into images section of images file
fsTrainingImages.release();                                                 // close the training images file

return(0);
#包括
#包括
#包括
#包括
#包括
#包括
//全局变量
const int MIN_等高线面积=30;
const int大小调整后的图像宽度=20;
const int RESIZED_IMAGE_HEIGHT=30;
//////////////////////////////////////
int main(){
cv::Mat imgTrainingNumbers;//输入图像
cv::Mat imgGrayscale;//
cv::Mat imgBlurred;//声明各种图像
cv::Mat imgThresh//
cv::Mat imgThreshCopy//
std::vector ptcourts;//声明轮廓向量
std::vector v4iHierarchy;//声明轮廓层次结构
cv::Mat MatClassificationts;//这些是我们的培训分类,请注意,在稍后写入文件之前,我们必须执行一些转换
//这些是我们的训练图像,由于KNN对象KNearest需要的数据类型,我们必须声明一个Mat,
//然后附加到它,就像它是一个向量一样,我们还必须在稍后写入文件之前执行一些转换
cv::Matt Mattraining Images展平浮点数;
//我们感兴趣的可能字符是数字0到9和大写字母A到Z,将它们放入向量intValidChars中
std::vector intValidChars={'0','1','2','3','4','5','6','7','8','9',',
‘A’、‘B’、‘C’、‘D’、‘E’、‘F’、‘G’、‘H’、‘I’、‘J’,
‘K’、‘L’、‘M’、‘N’、‘O’、‘P’、‘Q’、‘R’、‘S’、‘T’,
‘U’、‘V’、‘W’、‘X’、‘Y’、‘Z’};
imgTrainingNumbers=cv::imread(“caracteres_prueba.png”);//读取训练数字图像
if(imgTrainingNumbers.empty()){//if无法打开映像
STD::Couth-MixCouthUl区域){//如果轮廓足够大,可以考虑
cv::Rect boundingRect=cv::boundingRect(ptContours[i]);//获取边界矩形
cv::rectangle(imgTrainingNumbers,boundingRect,cv::Scalar(0,0,255),2);//当我们要求用户输入时,在每个轮廓周围绘制红色矩形
cv::Mat matROI=imgThresh(boundingRect);//获取boundingRect的ROI图像
cv::Mat拟阵化;
cv::resize(matROI,MATRORIZED,cv::Size(RESIZED_IMAGE_WIDTH,RESIZED_IMAGE_HEIGHT));//调整图像大小,这将使识别和存储更加一致
cv::imshow(“matROI”,matROI);//显示ROI图像以供参考
cv::imshow(“拟阵化”,拟阵化);//显示调整大小的ROI图像以供参考
cv::imshow(“imgTrainingNumbers”,imgTrainingNumbers);//显示训练编号图像,现在将在其上绘制红色矩形
int intChar=cv::waitKey(0);//获取按键
如果(intChar==27){//如果按了esc键
返回(0);//退出程序
}
else if(std::find(intValidChars.begin(),intValidChars.end(),intChar)!=intValidChars.end()){//else如果字符在我们要查找的字符列表中。
matClassificationts.push_back(intChar);//将分类字符附加到字符的整数列表中
cv::Mat matImageFloat;//现在添加训练图像(首先需要进行一些转换)。
MatroResized.convertTo(matImageFloat,CV_32FC1);//将Mat转换为float
cv::Mat MatimageFlattedFloat=matImageFloat.Reformate(1,1);//展平
MattrainingImagesAsFlattedFloats.push_back(MatImageFlattedFloat);//将其添加到Mat,就像它是一个向量一样,这是必要的,因为
//KNearest.train接受的数据类型
}//如果结束,则结束
}//如果结束,则结束
}//结束

std::cout首先,您在

 int intChar = cv::waitKey(0);
一定是

char intChar = cv::waitKey(0);

试试看,如果有错误告诉我,你可以在附近(垂直方向)聚集轮廓。这也是“i”的问题。(用英语编写代码也可能有帮助)对不起,我忘记编辑代码了,但我已经编辑过了,谢谢!将它们训练为两个独立的字符有什么问题,但在检测时,您可以编写特殊情况,将两个字符的检测视为单个字符。
int intChar=cv::waitKey(0)
完全可以。但是当您从屏幕上获取字符时,您必须声明作为char to可以获取数字和字符……。我以前使用过该代码,所以我告诉您发生了什么事
cv::waitKey
如果您按下任何键,将返回大于127的值,从而溢出
char
变量(范围从-128到127)因此,不建议将密钥代码存储在<代码> char 变量中。无论如何,您的答案与OP的问题无关,所以您应该考虑删除它。我知道,但是CV::WaTKEY将从您输入的键盘取值,因此如果它是int,则只取数字,但如果字符是字符和数字,那么它将取字符和数字。