Я пытаюсь создать некоторый код, который принимает цвет одной картинки и передает ее другой. Для этого я использую opencv для сегментации и обработки изображений.
Я создаю класс с именем Shape, который содержит контур одной фигуры (find с opencv findContours (), которая создает std :: vector>) случайная строка, которая служит идентификатором для объекта и cv :: Vec3b для цвета фигуры.
Но когда я перебираю контуры, найденные в opencv, и создаю один объект (класс Shape) и Если вы хотите добавить в список, он просто добавляет некоторые из них, а затем выдает ошибку сегментации на консоли.
Вот мой код:
#include <random>
#include <string>
#include <algorithm>
#include <opencv2/opencv.hpp>
using contourType = std::vector < std::vector < cv::Point > >;
std::string randomString ( )
{
auto randchar = [ ]( ) -> char {
const char charset[ ] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = ( sizeof ( charset ) - 1);
return charset[ rand ( ) % max_index ];
};
std::string str ( 14, 0 );
std::generate_n ( str.begin ( ), 14, randchar );
return str;
};
class Shape {
public:
std::string idShape;
std::vector < cv::Point > contour;
cv::Vec3b color;
Shape () {
};
void setShape ( std::vector < cv::Point > cnt, cv::Vec3b clr ) {
idShape = randomString ( );
contour = cnt;
color = clr;
};
cv::Point centroid ( bool showImage ) {
cv::Moments m = cv::moments ( contour, true );
cv::Point centroid ( m.m10 / m.m00, m.m01 / m.m00 );
return centroid;
};
};
class Frame {
public:
std::string idFrame;
cv::Size size;
int type;
std::vector < Shape > shapes;
Frame ( cv::Size imSize, int tp ) {
idFrame = randomString ( );
size = imSize;
type = tp;
};
int addShape ( Shape shape ) {
shapes.push_back ( shape );
return 0;
};
};
contourType findShapes ( cv::Mat img, bool showImage ) {
//Threshold
cv::adaptiveThreshold ( img, img, 255, cv::ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 5, 1 );
//Erotion
cv::Mat kernel = cv::getStructuringElement ( cv::MORPH_RECT, cv::Size ( 2, 2 ), cv::Point ( 0, 0 ) );
cv::erode ( img, img, kernel );
//Find contours
contourType contours;
cv::Mat contourImg = img.clone ( );
cv::findContours ( contourImg, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE );
shapes
//Show image if true 2nd. argument
if ( showImage == true ) {
cv::Mat contourImage ( img.size ( ), CV_8UC3, cv::Scalar ( 0, 0, 0 ) );
cv::Scalar colors[ 3 ];
colors[ 0 ] = cv::Scalar ( 255, 0, 0 );
colors[ 1 ] = cv::Scalar ( 0, 255, 0 );
colors[ 2 ] = cv::Scalar ( 0, 0, 255 );
for ( size_t idx = 0; idx < contours.size ( ); idx++ ) {
cv::drawContours ( contourImage, contours, idx, colors[ idx % 3 ], CV_FILLED /*thick*/ );
std::cout << idx;
};
cv::imshow ( "Contour Image", contourImage );
cv::waitKey ( 0 );
};
return contours;
};
cv::Vec3b findColor ( cv::Mat img, std::vector < cv::Point > contour, bool print ) {
//Read pixel intensity
cv::Vec3b intensity;
cv::Point coordinate = contour[ 1 ];
intensity = img.at < cv::Vec3b > ( coordinate );
//Print pixel values
if ( print == true ) {
std::cout << intensity << std::endl;
};
return intensity;
};
int main ( int argc, char** argv ) {
std::string url = argv[1];
int type = 0;
cv::Mat img;
img = cv::imread ( url, 0 );
Frame frame ( img.size ( ), type );
contourType shapes;
shapes = findShapes ( img, false );
cv::Mat imColor;
imColor = cv::imread ( url, 1 );
std::list<Shape> te;
for ( size_t i = 0; i < shapes.size ( ); i++ ) {
Shape shape;
shape.setShape ( shapes[i], findColor ( imColor, shapes[i], false ) );
te.push_back( shape ); //Here is where it fails after adding a few objects, running out of memory? The idea is to contain the Shape object inside the a Frame members shapes property. But i'm testing first like this, just adding it to a list.
};
return 0;
}
Он добавляет в список только 29 фигур, затем ошибка "ошибка сегментации (ядро сброшено)" появляется в консоли. Но изображение составляет около 67 фигур.