auto start_time = std::chrono::high_resolution_clock::now();
//do{
for (int process_direction = 2; process_direction != 0; --process_direction) {
count_holefill++;
for (int y = 1; y < binaryImage.rows - 1; y++) {
//shift row pointer by one
p_above = p_curr;
p_curr = p_below;
p_below = binaryImage.ptr<uchar>(y + 1);
p_result = MaskImage.ptr<uchar>(y);
//Init element points
no = &(p_above[0]);
ne = &(p_above[1]);
me = &(p_curr[0]);
ea = &(p_curr[1]);
so = &(p_below[0]);
se = &(p_below[1]);
for (int x = 1; x < binaryImage.cols - 1; x++) {
// shift col pointers left by one (scan left to right)
nw = no;
no = ne;
ne = &(p_above[x + 1]);
we = me;
me = ea;
ea = &(p_curr[x + 1]);
sw = so;
so = se;
se = &(p_below[x + 1]);
//A: 0-1 change number
//B: adjacent no-zeros numbers
int A = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) +
(*ea == 0 && *se == 1) + (*se == 0 && *so == 1) +
(*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) +
(*we == 0 && *nw == 1) + (*nw == 0 && *no == 1);
int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw;
// remove south or east edge and nor-west corner point.
if (process_direction == 2) {
int m1 = *no * *ea * *we;
int m2 = *no * *so * *we;
if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
p_result[x] = 1;
}
else if (process_direction == 1) {
int m1 = *no * *ea * *so;
int m2 = *ea * *so * *we;
if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
p_result[x] = 1;
}
else if ((process_direction != 1) && ((process_direction != 2))) {
LOG_F(ERROR, "process_direction is wrong!");
}
}
}
// thinning image
binaryImage &= ~MaskImage;
}
auto end_start = std::chrono::high_resolution_clock::now();
int comsurm_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_start - start_time).count();
#include “stdio.h”
#include “stdlib.h”
#include “time.h”
int main( void )
{
long i = 10000000L;
clock_t start, finish;
double duration;
/* 测量一个事件持续的时间*/
printf( "Time to do %ld empty loops is ", i );
start = clock();
while( i-- ) ;
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
printf( "%f seconds\n", duration );
system("pause");
}
#include <cmath>
#include <iostream>
#include <memory>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/video/background_segm.hpp>
#include "opencv2/calib3d/calib3d.hpp"
#include <opencv2/opencv.hpp>
#include <time.h>
#include <thread>
#include <future>
#include <chrono>
#include <vector>
#include "time.h"
#include <string>
#include <fstream>
using namespace std;
using namespace cv;
RNG rng;
const Point neighbors[8] = { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 },
{ 0, -1 }, { -1, -1 }, { -1, 0 }, {-1, 1} };
void ThinningEdgeIteration(cv::Mat& outimage, int process_direction)
{
cv::Mat MaskImage = cv::Mat::zeros(outimage.size(), CV_8UC1);
uchar* p_result = MaskImage.ptr<uchar>(0);
int n_rows = outimage.rows;
int n_cols = outimage.cols;
cv::Mat LabelPoint = cv::Mat::zeros(outimage.size(), CV_8UC1);
{
int x, y;
uchar* p_above;
uchar* p_curr;
uchar* p_below;
//Releatve to center point'local position
//west:w east:e north:n south:s
uchar* nw, * no, * ne; // north (p_above)
uchar* we, * me, * ea; //west median east
uchar* sw, * so, * se; // south (p_below)
// initialize pointers
p_above = NULL;
p_curr = outimage.ptr<uchar>(0);
p_below = outimage.ptr<uchar>(1);
uchar* p_result1 = LabelPoint.ptr<uchar>(0);
for (int y = 1; y < outimage.rows - 1; y++) {
//shift row pointer by one
p_above = p_curr;
p_curr = p_below;
p_below = outimage.ptr<uchar>(y + 1);
p_result1 = LabelPoint.ptr<uchar>(y);
//Init element points
no = &(p_above[0]);
ne = &(p_above[1]);
me = &(p_curr[0]);
ea = &(p_curr[1]);
so = &(p_below[0]);
se = &(p_below[1]);
for (int x = 1; x < outimage.cols - 1; x++) {
// shift col pointers left by one (scan left to right)
nw = no;
no = ne;
ne = &(p_above[x + 1]);
we = me;
me = ea;
ea = &(p_curr[x + 1]);
sw = so;
so = se;
se = &(p_below[x + 1]);
// reference pager:A fast parallel algorithm for thinning digital patterns
//B: adjacent no-zeros numbers
int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw;
if (B == 8)
p_result1[x] = 1;
}
}
outimage &= ~LabelPoint;
}
if (outimage.isContinuous()) {
n_cols *= n_rows;
n_rows = 1;
}
int x, y;
uchar* p_above;
uchar* p_curr;
uchar* p_below;
//Releatve to center point'local position
//west:w east:e north:n south:s
uchar* nw, * no, * ne; // north (p_above)
uchar* we, * me, * ea; //west median east
uchar* sw, * so, * se; // south (p_below)
// initialize pointers
p_above = NULL;
p_curr = outimage.ptr<uchar>(0);
p_below = outimage.ptr<uchar>(1);
for (int y = 1; y < outimage.rows - 1; y++) {
//shift row pointer by one
p_above = p_curr;
p_curr = p_below;
p_below = outimage.ptr<uchar>(y + 1);
p_result = MaskImage.ptr<uchar>(y);
//Init element points
no = &(p_above[0]);
ne = &(p_above[1]);
me = &(p_curr[0]);
ea = &(p_curr[1]);
so = &(p_below[0]);
se = &(p_below[1]);
for (int x = 1; x < outimage.cols - 1; x++) {
// shift col pointers left by one (scan left to right)
nw = no;
no = ne;
ne = &(p_above[x + 1]);
we = me;
me = ea;
ea = &(p_curr[x + 1]);
sw = so;
so = se;
se = &(p_below[x + 1]);
// reference pager:A fast parallel algorithm for thinning digital patterns
//A: 0-1 change number
//B: adjacent no-zeros numbers
//
int A = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) +
(*ea == 0 && *se == 1) + (*se == 0 && *so == 1) +
(*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) +
(*we == 0 && *nw == 1) + (*nw == 0 && *no == 1);
int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw;
// remove south or east edge and nor-west corner point.
int m1 = process_direction == 0 ? (*no * *ea * *so) : (*no * *ea * *we);
int m2 = process_direction == 0 ? (*ea * *so * *we) : (*no * *so * *we);
if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
p_result[x] = 1;
}
}
// thinning image
outimage &= ~MaskImage;
}
void EdgeGrow(cv::Mat& edges, vector<vector<Point>>& contours)
{
vector<Point> contour;
contour.reserve(100);
cv::Point start_point, current_point;
int i, j, counts = 0, curr_direction = 0;
for (i = 1; i < edges.rows - 1; i++)
for (j = 1; j < edges.cols - 1; j++) {
cv::Point center(j, i);
if (edges.at<uchar>(i, j) > 0) {
start_point = center;
current_point = center;
contour.clear();
edges.at<uchar>(i, j) = 0;
int stop_flag = 1;
contour.emplace_back(center);
// 8 neighbour no element
while (stop_flag) {
for (counts = 0; counts < 8; counts++) {
if (curr_direction >= 8) {
curr_direction -= 8;
}
if (curr_direction < 0) {
curr_direction += 8;
}
current_point = start_point + neighbors[curr_direction];
//valid condition
if (current_point.x > 0 && current_point.x < edges.cols - 1 && current_point.y>0 && current_point.y < edges.rows - 1) {
if (edges.at<uchar>(current_point.y, current_point.x) > 0) {
curr_direction -= 2;
contour.push_back(current_point);
edges.at<uchar>(current_point.y, current_point.x) = 0;
start_point = current_point;
break;// go counts
}
}
curr_direction++;
}
if (8 == counts) {
curr_direction = 0;
stop_flag = 0;
if (contour.size() > 10) {
contours.emplace_back(contour);
}
break;
}
}
}
}
Mat trace_edge = Mat::zeros(edges.rows, edges.cols, CV_8UC1);
Mat trace_edge_color;
cvtColor(trace_edge, trace_edge_color, CV_GRAY2BGR);
RNG rng(time(0));
for (i = 0; i < contours.size(); i++) {
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
if (contours[i].size() > 5) {
for (j = 0; j < contours[i].size(); j++) {
trace_edge_color.at<Vec3b>(contours[i][j].y, contours[i][j].x)[0] = color[0];
trace_edge_color.at<Vec3b>(contours[i][j].y, contours[i][j].x)[1] = color[1];
trace_edge_color.at<Vec3b>(contours[i][j].y, contours[i][j].x)[2] = color[2];
}
}
}
cv::imwrite("..\\example\\trac_edge_color.bmp", trace_edge_color);
}
void filltest(cv::Mat& input_image, cv::Mat& output_image)
{
cv::Mat thin_image = cv::Mat::zeros(input_image.rows, input_image.cols, CV_16UC1);
memcpy(thin_image.data, (uint16_t*)input_image.data, input_image.rows * input_image.cols * sizeof(uint16_t));
cv::Mat binary_image = cv::Mat::zeros(input_image.rows, input_image.cols, CV_8UC1);
binary_image = thin_image > 0;
cv::threshold(binary_image, binary_image, 50, 1, CV_THRESH_BINARY);
cv::Mat prev = cv::Mat::zeros(thin_image.size(), CV_8UC1);
cv::Mat diff;
do {
ThinningEdgeIteration(binary_image, 1);
ThinningEdgeIteration(binary_image, 0);
cv::absdiff(binary_image, prev, diff);
binary_image.copyTo(prev);
} while (cv::countNonZero(diff) > 0);
output_image = binary_image.clone();
vector<vector<Point>> contours;
EdgeGrow(binary_image, contours);
vector<vector<Point>> contour_temp;
//average value fill
for (int i = 0; i < contours.size(); i++)
{
int value = 0;
int scale = 0;
if (contours[i].size() < 500) {
for (int j = 0; j < contours[i].size(); j = j + 7) {
value += input_image.at<uint16_t>(contours[i][j].y, contours[i][j].x);
scale++;
}
contour_temp.emplace_back(contours[i]);
cv::fillPoly(input_image, contour_temp, value / scale);
contour_temp.clear();
}
cv::imwrite("..\\example\\fill_output_imge.png", input_image);
}
}
int main(int argc, char** argv) {
cv::Mat temp_thin = cv::imread("../example/2.jpg", CV_LOAD_IMAGE_UNCHANGED);
cv::Mat gray_image, GaussianBlur_image;
cvtColor(temp_thin, gray_image, CV_RGB2GRAY);
cv::Mat binary_image, middle_image;
cv::threshold(gray_image, binary_image, 50, 1, CV_THRESH_BINARY);
cv::Mat prev = cv::Mat::zeros(temp_thin.size(), CV_8UC1);
cv::Mat diff;
do {
ThinningEdgeIteration(binary_image, 1);
ThinningEdgeIteration(binary_image, 0);
cv::absdiff(binary_image, prev, diff);
binary_image.copyTo(prev);
} while (cv::countNonZero(diff) > 0);
middle_image = binary_image.clone();
/*cv::imshow("edge_image", edge_image);*/
vector<vector<Point>> contours;
EdgeGrow(binary_image, contours);
vector<vector<Point>> contour_temp;
//average value fill
for (int i = 0; i < contours.size(); i++)
{
int value = 0;
int scale = 0;
if (contours[i].size() < 500) {
for (int j = 0; j < contours[i].size(); j = j + 7) {
value += temp_thin.at<uint16_t>(contours[i][j].y, contours[i][j].x);
scale++;
}
contour_temp.emplace_back(contours[i]);
cv::fillPoly(temp_thin, contour_temp, value / scale);
contour_temp.clear();
}
cv::imwrite("..\\example\\fill_output_imge.png", temp_thin);
}
cv::waitKey(0);
return 0;
}