#c #function #opencv #byval
#c #функция #opencv #бывал
Вопрос:
У меня проблема с этим кодом:
Проблема в том, что когда я вижу оригинал изображения, он модифицируется «borrarFondo ()», но эта функция вызывается из «segmentarHoja», и здесь вводится img по значению, но img изменяется.
void borrarFondo(Matamp; img){
img = ~img;
Mat background;
medianBlur(img, background, 45);
GaussianBlur(background, background, Size(203,203),101,101);
img = img - background;
img = ~img;
}
void segmentarHoja(Mat img, Matamp; imsheet){
Mat imgbw;
borrarFondo(img); //borrarFondo is called from here where img is a copy
cvtColor(img, imgbw, CV_BGR2GRAY);
threshold(imgbw, imgbw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Mat element = getStructuringElement(MORPH_ELLIPSE, Size(21,21));
erode(imgbw, imgbw, element);
vector<vector<Point> > contoursSheet;
findContours(imgbw, contoursSheet, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
vector<Rect> boundSheet(contoursSheet.size());
int largest_area=0;
for( int i = 0; i< contoursSheet.size(); i )
{
double a= contourArea( contoursSheet[i],false);
if(a>largest_area){
largest_area=a;
boundSheet[i] = boundingRect(contoursSheet[i]);
imsheet=img(boundSheet[i]).clone();
}
}
borrarFondo(imsheet);
}
int main()
{
Mat imsheet;
image= imread("c:/imagen.jpg");
segmentarHoja(image, imsheet);
imshow("imsheet",imsheet);
imshow("imagen",image); //original image by amending borrarFondo
waitKey(0);
}
Я не хочу менять исходное изображение
Комментарии:
1.
void borrarFondo(Matamp; img)
Вы не передавали по значению, вы передавали по ссылке. Именно поэтому вы изменяетеimg
.2. насколько я могу вспомнить, opencv
Mat
— это ссылка с подсчетом ссылок (т. Е. likestd::shared_ptr
, за исключением другого синтаксиса), где конструкция копирования или присваивание не копируются. хорошо, я только что проверил документы, что вы и должны были сделать. используйтеclone
метод для копирования.3. @Cyber: нет, это не так, хотя это было бы естественным выводом, если ничего не знать
Mat
.4. но эта функция вызывается из другой функции «segmentarHoja», где img передается по значению. В основном вызове segmentarHoja и в segmentarhoja вызов borrarFondo, img изменяется в segmentarHoja, но img в segmentarHoja передается по значению
Ответ №1:
opencv Mat
— это подсчитанная ссылка (т. Е. Похожая std::shared_ptr
, за исключением другого синтаксиса), где конструкция копирования или присваивание не копируются. используйте clone
метод для копирования. прочитайте документацию, это всегда хорошая идея.
Комментарии:
1. тогда я не могу передать
Mat
по значению? следует ли передавать копиюMat
withclone
?2. Кстати, я также рассмотрел этот вопрос и ответ в соответствии с моим убеждением в том, что каждый обязан преподавать правильные вещи везде, где он сталкивается с неправильными представлениями. Но это становится утомительным, и мало кто хочет это делать. Так что просто будьте осторожны с советами, которые вы получаете на SO.
3. спасибо за все, я не очень понимаю по-английски, но я стараюсь узнать все об обработке изображений, и на испанском языке нет информации об этом xD, у меня есть школьный проект, который нужно сделать, я не подумал, что лучше что-то с opencv xD, теперь я должен это сделать
4. еще один вопрос, искусственный интеллект очень сложный? или через месяц я это понимаю?
5. @user3779874: Учтите, что некоторые из лучших умов на планете боролись с исследованиями и пытались создать искусственный интеллект с 1950-х годов, но пока безуспешно, и вы можете сделать вывод, что есть чему поучиться. Несмотря на это, простая арифметика говорит вам, что до получения необходимой мощности машины еще около 20-30 или более лет. Искусственный интеллект — это современное состояние, и это очень подвижная цель… НО , может быть, вы говорите о «движке искусственного интеллекта» игры. Я думаю, это нечто гораздо более практичное, о чем можно узнать. 🙂
Ответ №2:
если вы делаете что-то подобное:
Mat a;
Mat b = a;
или как это:
void func(Mat m) {...}
или :
vector<Mat> vm;
vm.push_back(m);
все это мелкая копия. заголовок Mat будет копией, указатели внутри тоже.
так, например, в 1-м примере b и a имеют одинаковый размер и элементы данных
это может объяснить, почему передача Mat по значению по-прежнему приводит к тому, что пиксели обрабатываются из «мелкой» копии.
чтобы избежать этого, вам придется вместо этого выполнить «глубокую» копию:
Mat c = a.clone(); // c has its own pixels now.
и снова, если вы не хотите, чтобы вашим Mat можно было манипулировать, передайте его как a будьте очень осторожны в том, как вы его используете, как показано ниже. const Mat amp;
#include <opencv2/opencv.hpp>
void foo( cv::Mat constamp; image )
{
cv::Mat result = image;
cv::ellipse(
result, // img
cv::Point( 300, 300 ), // center
cv::Size( 50, 50 ), // axes (bounding box size)
0.0, // angle
0.0, // startAngle
360.0, // endAngle
cv::Scalar_<int>( 0, 0, 255 ), // color
6 // thickness
);
}
auto main() -> int
{
auto window_name = "Display";
cv::Mat lenna = cv::imread( "lenna.png" );
foo( lenna );
imshow( window_name, lenna );
cv::waitKey( 0 );
}
Mat constamp;
Ложь о изменчивости, и нос Ленны соответственно длинный, здесь отмечен большим жирным кругом, помещенным foo
функцией выше:
Комментарии:
1. хе-хе, ок. верно. 😉 спасибо, что указали, @Cheers и hth. — Alf