OpenCV 【二】————计算时间---八近邻细化边缘跟踪(图像边缘提取与填充)——边缘提取实现

    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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大江东去浪淘尽千古风流人物

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值