This question relates to somewhat practice and experienced based process. I have an Mat binary image which consist of simple white color polygons in a black background. Actually those polygons represent an article in a newspaper page. So what I want is to store the details of the location of the article inside the newspaper page. One Mat image has only one polygon in it. So one option is to
Following is a sample image of a Mat I am going to store.
The first option seems possible but I don't know how to implement the second approach. If it is possible, that would be most efficient as I think, because then there would be only few coordinates to be saved for each article. I can implement a complex procedure to find the vertices for that and also to redraw the Mat image using those coordinates when needed. But I hope there is a simple process in opencv for this task.
So what I want to know is which approach is better and if the second approach is better, how to do that in opencv with c++. I am neither an opencv expert nor c++ expert so an appropriate answer would save me many hours and also efficiency of the program.
You can simply use findContours, with an appropriate contour approximation method. Basically, aside from CV_CHAIN_APPROX_NONE
that will store all points, every other method is fine for this example: CV_CHAIN_APPROX_SIMPLE
, CV_CHAIN_APPROX_TC89_L1
and CV_CHAIN_APPROX_TC89_KCOS
.
You can store those points in your database. You can then reload those points, and draw original image with fillPoly.
This simple example show the retrieved contours points with the approximation method, and how to re-draw the image with those points.
Note that you're image is aliased (you probably saved it in jpeg before png), so you need to remove aliasing for example keeping only points with value equals to 255.
#include <opencv2\opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main()
{
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Removing compression artifacts
img = img == 255;
vector<vector<Point>> contours;
findContours(img.clone(), contours, RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
if (contours.empty()) {return -1;}
// Save the vertices "contours[0]"
// Result image
Mat3b res;
cvtColor(img, res, COLOR_GRAY2BGR);
for (int i = 0; i < contours[0].size(); ++i)
{
circle(res, contours[0][i], 3, Scalar(0,255,0));
}
// Reconstruct image from contours vertex
// Load the vertices
vector<vector<Point>> vertices = { contours[0] };
Mat1b rec(img.rows, img.cols, uchar(0));
fillPoly(rec, vertices, Scalar(255));
imshow("Vertices", res);
imshow("Reconstructed", rec);
waitKey();
return 0;
}
Green vertices with contour approximation method: