c++ - 绘画渲染,剪裁线,我有一个错误

标签 c++ opencv

enter image description here 我正在制作绘画效果图。 现在我正在做剪裁线的事情。 但是我得到了这个错误:

<<unsigned><pt.x*DataType<_Tp>::channels> <<unsigned<size.p[1]*channels<>>>

template<typename _Tp> inline const _Tp& Mat::at(int i0, int i1) const
{
    CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] &&
        (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) &&
        CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
    return ((const _Tp*)(data + step.p[0]*i0))[i1];
}

也许这是'Lineclipping()' 的错误

请告诉我另一个剪线的好主意。

这是我的代码。而且我只是一名学生,所以我的编码技能非常初级。

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <sstream>
#include <cmath>
#include <stdio.h>
#include <cstdlib>
#include <time.h>
#include <random>

using namespace cv;
using namespace std;

random_device rd;
mt19937_64 rng(rd());
double PI = 3.141592;

int perturbLength = (rand() % 6) + 1;
int perturbRadius = ((rand() % 5) + 0) / 10;
int perturbAngle = (rand() % 15) + (-15);

int Maxlength = 10 - perturbLength;
int radius = 2 - perturbRadius;
int angle = 45 - perturbAngle;
double theta = angle*(PI / 180);

void Lineclipping(int x, int y, double theta, int len, Point2d& pt1, Point2d& pt2, Mat& EdgeMap)
{
    double length = ceil(len);
    enter code here
    float detectPT = len / length;

    for (int i = detectPT; i <= len;)
    {
        Point2d Mpt1(x + length*cos(theta), y + length*sin(theta));

        if (EdgeMap.at<uchar>(Mpt1.y, Mpt1.x) > 0)
        {
            pt1.x = Mpt1.x;
            pt1.y = Mpt1.y;
        }
        else if (i == length)
        {
            pt1.x = Mpt1.x;
            pt1.y = Mpt1.y;
        }
        i = i + detectPT;
    }
    for (int i = detectPT; i <= len;)
    {
        Point2d Mpt2(x - length*cos(theta), y - length*sin(theta));

        if (EdgeMap.at<uchar>(Mpt2.y, Mpt2.x) > 0)
        {
            pt2.x = Mpt2.x;
            pt2.y = Mpt2.y;
        }
        else if (i == length)
        {
            pt2.x = Mpt2.x;
            pt2.y = Mpt2.y;
        }
        i = i + detectPT;
    }


}

Mat EdgeDetect(Mat& referenceimg, Mat& Edge)
{
    Mat image = referenceimg.clone();

    //Make Edge Map
    Mat IntensityImg(image.size(), CV_8U, 255);
    Mat sobelx, sobely;

    for (int i = 0; i < image.rows; i++)
    {
        for (int j = 0; j < image.cols; j++)
        {
            Vec3b intensity = image.at<Vec3b>(j, i);
            uchar blue = intensity.val[0];
            uchar green = intensity.val[1];
            uchar red = intensity.val[2];
            IntensityImg.at<uchar>(j, i) = (30 * red + 59 * green + 11 * blue) / 100;

        }
    }
    GaussianBlur(IntensityImg, IntensityImg, Size(5, 5), 0.1, 0.1);
    Sobel(IntensityImg, sobelx, CV_32F, 1, 0);
    Sobel(IntensityImg, sobely, CV_32F, 0, 1);
    Mat magnitudeXY = abs(sobelx), abs(sobely);

    magnitudeXY.convertTo(Edge, CV_8U);

    Mat mask(3, 3, CV_8UC1, 1);
    morphologyEx(Edge, Edge, MORPH_ERODE, mask);

    for (int i = 0; i < image.rows; i++)
    {
        for (int j = 0; j < image.cols; j++)
        {
            Edge.at<uchar>(j, i) = (Edge.at<uchar>(j, i) > 20 ? 255 : 0);
        }
    }


    imshow("intensity", Edge);

    return Edge;
}

void paint(Mat &image, int snum)
{
    Mat Edge;

    EdgeDetect(image, Edge);

    for (int n = 0; n < snum; n++)
    {
        int x = rand() % image.cols;
        int y = rand() % image.rows;

        if (image.channels() == 1)
        {
            image.at<uchar>(x, y) = 255;
        }
        else if (image.channels() == 3)
        {

            int length = Maxlength / 2;

            Point2d pt1(x + length*cos(theta), y + length*sin(theta));
            Point2d pt2(x - length*cos(theta), y - length*sin(theta));

            Lineclipping(x, y, theta, length, fpt1, fpt2, Edge);

            //draw line
            Scalar color(image.at<Vec3b>(y, x)[0], image.at<Vec3b>(y, x)[1], image.at<Vec3b>(y, x)[2]);
            line(image, pt1, pt2, color, radius);

        }
    }

}

int main()
{
    Mat Img = imread("fruit.jpg", IMREAD_COLOR);
    CV_Assert(Img.data);
    Mat resultImage = Img.clone();
    Mat sobel = Img.clone();
    int num = Img.rows*Img.cols;

    paint(resultImage, num);

    imshow("result", resultImage);
    waitKey();
    return 0;
}

这是错误的部分。

for (int i = detectPT; i <= len;)
        {
            Point2d Mpt1(x + length*cos(theta), y + length*sin(theta));

            if (EdgeMap.at<uchar>(Mpt1.y, Mpt1.x) > 0)
            {
                pt1.x = Mpt1.x;
                pt1.y = Mpt1.y;
            }
            else if (i == length)
            {
                pt1.x = Mpt1.x;
                pt1.y = Mpt1.y;
            }
            i = i + detectPT;
        }
        for (int i = detectPT; i <= len;)
        {
            Point2d Mpt2(x - length*cos(theta), y - length*sin(theta));

            if (EdgeMap.at<uchar>(Mpt2.y, Mpt2.x) > 0)
            {
                pt2.x = Mpt2.x;
                pt2.y = Mpt2.y;
            }
            else if (i == length)
            {
                pt2.x = Mpt2.x;
                pt2.y = Mpt2.y;
            }
            i = i + detectPT;
        }

谢谢!

最佳答案

由于我无法编译和运行它,我将运行一个可能的执行并向您展示在哪里可以遇到这个超出范围的错误。

int perturbLength = (rand() % 6) + 1; // Range is 1 to 6, let's assume 4
int perturbAngle = (rand() % 15) + (-15);  // Range is -15 to -1 let's assume -14

int Maxlength = 10 - perturbLength; // 6
int angle = 45 - perturbAngle; // 44 
double theta = angle*(PI / 180); // .7679

现在我们进入 paint 方法中的这段代码:

int x = rand() % image.cols; // Let's assume image.cols - 2
int y = rand() % image.rows; // Let's assume image.rows - 1

paint 内部,我们将得到这段代码:

int length = Maxlength / 2;  // Maxlength is 6 so this is 3
Lineclipping(x, y, theta, length, fpt1, fpt2, Edge);

这导致了 Lineclipping 方法,这里我们遇到了一个问题:

Point2d Mpt1(x + length*cos(theta), y + length*sin(theta));

if (EdgeMap.at<uchar>(Mpt1.y, Mpt1.x) > 0)

这就是问题所在。请记住,x 是 image.cols - 2。现在我们执行操作 x + length * cos(theta),即 (image.cols-2) + 3 * cos(.7679 )。 3 * cos(.7679) 是 2.999,当您将它添加到 image.cols - 2 时,无论您将它平整还是圆整都会导致问题。如果它是 floored 并且你得到 2 我们有 image.cols 导致超出范围,如果它是四舍五入那么我们有 image.cols + 1,所以在任何一种情况下我们超出了数组的范围。

关于c++ - 绘画渲染,剪裁线,我有一个错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49548546/

相关文章:

python-2.7 - SVM自定义对象检测器的正负样本分别

c++ - 使用 Net-SNMP 的 snmpset 的多个值

c++ - OpenCV 具有相似颜色背景的颜色检测

颜色转换在 opencv 中不起作用?

python - 如何提取适合粗线轮廓中间的线方程

python - 如何垂直合并/附加/堆叠/粘贴文件夹中的所有图像到新图像

c++ - C++11 中对数组的右值引用的目的是什么?

c++ - 通用单链表的错误,C++

c++ - 将 MIPS 代码移植到 x86_64 时的浮点差异

c++ - 如何用随机数填充文件?