如何将具有特定大小的字符复制到另一个图像中与原始图像相同的位置?

Posted

技术标签:

【中文标题】如何将具有特定大小的字符复制到另一个图像中与原始图像相同的位置?【英文标题】:How copy the character with the specific size in another image at the same position as it was in the original image? 【发布时间】:2014-06-25 13:41:32 【问题描述】:

我开发了一个应用程序来识别图像中的文本。图像包含大量噪点。这就是为什么当我处理检测图像中的边缘时,我只考虑具有特定尺寸的边缘。我会解释更多。

This 是我的原图。我应用边缘检测,然后提取例如第一个字符“C”

    Mat img(aux,Rect(x,y,width,height));

现在我创建一个与原始大小相同的白色图像。

    Mat image=cvCreateMat(original.rows,original.cols,original.type());
    image.setTo(cv::Scalar::all(255));

现在我想将 Mat 图像中的“C”字符复制到与原始图像相同的位置。我这样做了,但它给了我一个错误的结果。

    int j=10,x=40;
    cout<<img.rows<<" "<<img.cols;

    for (int k=0;k<img.cols;k++)
        for(int i=0;i<img.rows;i++)
        image.at<uchar>(x,j)=img.at<uchar>(i,k );
        j++;
    
    j=j+aux.rows-40;
    x++;

请帮忙

【问题讨论】:

img 是您的原始图像,image 是您的空图像?字符“C”在哪里?是在x=40, y=10,它的尺寸(宽度/高度)是多少? img 是包含“C”字符的图像,我从原始图像中提取它。字符“C”在 X=40,y=10 字符“C”的大小是多少,以像素为单位:宽度和高度? imgimage/original 有什么像素类型?或者img 是否包含ONYL 字符“C”而没有其他内容?` 请也上传img... 我还将高度和宽度记为 img.cols 和 img.rows。 img, image 和 original 都是黑白图像。 黑白配8UC1类型还是黑白配8UC3(例如加载imread)? 【参考方案1】:

这是.copyTo 的方法:

    int main()
    
        //here: read original image as 8UC3 (which is an RBG image)
        cv::Mat original = cv::imread("characterC_original.png");

        // here: read original image as 8UC1 (which is grayscale)
        //cv::Mat original = cv::imread("characterC_original.png", CV_LOAD_IMAGE_GRAYSCALE);

        // this is the image with the character only. In 8UC3 type too
        cv::Mat img = cv::imread("characterC.png");
        //cv::Mat img = cv::imread("characterC.png", CV_LOAD_IMAGE_GRAYSCALE);

        // this is where the character was placed in original. If you have this information already somehwere else, you can use that directly. So you don't even need to have that `img` if you know offset, width and height
        int offsetX = 40;
        int offsetY = 10;
        int width = img.cols;
        int height = img.rows;

        cv::Rect characterLocation = cv::Rect(offsetX, offsetY, width, height);

        cv::Mat image = cv::Mat(original.rows, original.cols, original.type());
        image.setTo(cv::Scalar::all(255));

        original(characterLocation).copyTo(image(characterLocation));

        cv::imshow("original", original);
        cv::imshow("char copied", image);
        cv::imwrite("characterC_result.png", image);
        cv::waitKey(-1);
    

给我这个结果:

【讨论】:

【参考方案2】:

假设img 已经是包含角色的子图像,并且您知道该子图像在原始图像中的位置,并且两个图像都是8UC1type:

int offsetY=10;
int offsetX=40;

for(int j=0;j<img.rows;j++)
    for (int i=0;i<img.cols;i++)
    

        image.at<uchar>(j+offsetY,i+offsetX)=img.at<uchar>(j,i);
    

如果两个图像都不是8UC1 类型而是8UC3 类型,请将&lt;uchar&gt; 替换为&lt;Vec3b&gt;. If one of them is8UC1and the other is8UC3` 您必须先转换或手动转换。

如果imgoriginal 未更改子图像,您可以轻松地直接使用和复制子图像,而无需创建img,这样会更快,并且您不必关心类型。

以下是两个例子:

灰度图像:

    int main()
    
        // here: read original image as 8UC1 (which is grayscale)
        cv::Mat original = cv::imread("characterC_original.png", CV_LOAD_IMAGE_GRAYSCALE);

        // this is the image with the character only. In 8UC1 type too
        cv::Mat img = cv::imread("characterC.png", CV_LOAD_IMAGE_GRAYSCALE);

        // this is where the character was placed in original. If you have this informationalready somehwere else, you can use that directly.
        int offsetX = 40;
        int offsetY = 10;
        int width = img.cols;
        int height = img.rows;


        cv::Mat image = cv::Mat(original.rows, original.cols, original.type());
        image.setTo(cv::Scalar::all(255));


        for(int j=0;j<img.rows;j++)
            for (int i=0;i<img.cols;i++)
            
// here you use uchar since it's 8UC1
                image.at<uchar>(j+offsetY,i+offsetX)=img.at<uchar>(j,i);
            

        cv::imshow("original", original);
        cv::imshow("char copied", image);
        cv::imwrite("characterC_result_8UC1.png", image);
        cv::waitKey(-1);
    

这是嵌入在 RGB 图像中的黑白图像:

    int main()
    
        //here: read original image as 8UC3 (which is an RBG image)
        cv::Mat original = cv::imread("characterC_original.png");

        // this is the image with the character only. In 8UC3 type too
        cv::Mat img = cv::imread("characterC.png");

        // this is where the character was placed in original. If you have this informationalready somehwere else, you can use that directly.
        int offsetX = 40;
        int offsetY = 10;
        int width = img.cols;
        int height = img.rows;


        cv::Mat image = cv::Mat(original.rows, original.cols, original.type());
        image.setTo(cv::Scalar::all(255));


        for(int j=0;j<img.rows;j++)
            for (int i=0;i<img.cols;i++)
            
// here you use Vec3b since you have RGB type
                image.at<cv::Vec3b>(j+offsetY,i+offsetX)=img.at<cv::Vec3b>(j,i);
            

        cv::imshow("original", original);
        cv::imshow("char copied", image);
        cv::imwrite("characterC_result_8UC3.png", image);
        cv::waitKey(-1);
    

我对两者都进行了测试,它们都可以工作。

【讨论】:

这是图片dropbox.com/s/p5e4wikqjtnguok/image.png,我想得到这个结果dropbox.com/s/fpt5t5rv4qvmroy/result.png

以上是关于如何将具有特定大小的字符复制到另一个图像中与原始图像相同的位置?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Konva.js 将图像复制/粘贴到另一个图像?

有一些特定的图像文件,需要将选定的文件复制到另一个文件夹

如何将任意路径从一个 UIImage 复制到另一个

如何保存具有特定文件大小的图像?

如何将字符串从一个 winform 应用程序发送到另一个应用程序? [复制]

OpenCV如何将GpuMat复制到另一个GPU指针并复制回来以验证正确性?