万门cpp作业:写模板函数实现find_all和sort排序

本文深入探讨了通用模板函数在C++中实现排序(sort)和查找(find_all)的应用。通过具体示例,如整数、浮点数和字符串的排序,以及在不同容器中查找特定元素,展示了算法的灵活性和效率。

sort 排序

#include<iostream>
#include<string>
#include<vector>
using namespace std;

template<class T>
void sort(T& input) {
	int l = input.size();
	for (int beg = l - 1; beg > 0; --beg)
		for (int i = 0; i < beg; ++i)
			if (input[i] > input[i + 1])
				swap(input[i], input[i + 1]);
	for (auto i : input)
		cout << i << "\n";
}

int main() { 
	vector<int> a{ 1,6,3,2,8,9 };
	sort(a);
	vector<double> b{ 1.1,1.2,1.6,1.5,1.8 };
	sort(b);
	string s = "1987634";
	sort(s);
	system("Pause");
	return 0;
}

在这里插入图片描述
find_all的实现

#include<iostream>
#include<string>
#include<vector>
#include<list>
using namespace std;

template<class T1,class T2>
vector<typename T1::iterator>
find_all(T1& input, const T2& val) {
	vector<typename T1::iterator> res;
	//T* head = &res;
	for (auto it = input.begin(); it != input.end(); ++it) {
		if (*it == val)
		{ res.push_back(it); }
	}
	return res;
}

void test() {
	string m { "mary had a little lamb" };
	for (auto p : find_all(m, 'a'))
		if (*p != 'a')
			cerr << "string bug!\n";
		else
			cout << "string is no bug!!" << endl;
	list<double> ld { 1.1,2.2,3.3,1.1 };
	for (auto p : find_all(ld, 1.1))
		if (*p != 1.1)
			cerr << "list bug!\n";
		else
			cout <<"list is no bug!!" << endl;
	vector<string> vs { "red","blue","green","green","orange","green" };
	for (auto p :find_all(vs,"red"))
		if(*p != "red")
			cerr << "vector bug!\n";
		else
			cout << "vector<list> is no bug!!" << endl;
	for (auto p : find_all(vs, "green")) {
		*p = "vert";
		cout << "this is vs gree"<<*p << endl;
	}
}

int main() {
	test();
	system("Pause");
	return 0;
}

在这里插入图片描述

这里主要是学会使用这个T::iterator 来访问容器元素的类型,加一个typename 来告诉编译器这是一个类型名称。

||=== Build file: "no target" in "no project" (compiler: unknown) ===| D:\1.cpp||In member function 'void GradeManager::load_from_file(const string&)':| D:\1.cpp|65|error: no matching function for call to 'std::basic_ifstream<char>::basic_ifstream(const string&)'| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|495|note: candidate: std::basic_ifstream<_CharT, _Traits>::basic_ifstream(const char*, std::ios_base::openmode) [with _CharT = char; _Traits = std::char_traits<char>; std::ios_base::openmode = std::_Ios_Openmode]| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|495|note: no known conversion for argument 1 from 'const string {aka const std::__cxx11::basic_string<char>}' to 'const char*'| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|481|note: candidate: std::basic_ifstream<_CharT, _Traits>::basic_ifstream() [with _CharT = char; _Traits = std::char_traits<char>]| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|481|note: candidate expects 0 arguments, 1 provided| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|455|note: candidate: std::basic_ifstream<char>::basic_ifstream(const std::basic_ifstream<char>&)| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|455|note: no known conversion for argument 1 from 'const string {aka const std::__cxx11::basic_string<char>}' to 'const std::basic_ifstream<char>&'| D:\1.cpp|75|error: variable 'std::istringstream iss' has initializer but incomplete type| D:\1.cpp||In member function 'void GradeManager::save_to_file(const string&)':| D:\1.cpp|82|error: no matching function for call to 'std::basic_ofstream<char>::basic_ofstream(const string&)'| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|697|note: candidate: std::basic_ofstream<_CharT, _Traits>::basic_ofstream(const char*, std::ios_base::openmode) [with _CharT = char; _Traits = std::char_traits<char>; std::ios_base::openmode = std::_Ios_Openmode]| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|697|note: no known conversion for argument 1 from 'const string {aka const std::__cxx11::basic_string<char>}' to 'const char*'| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|682|note: candidate: std::basic_ofstream<_CharT, _Traits>::basic_ofstream() [with _CharT = char; _Traits = std::char_traits<char>]| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|682|note: candidate expects 0 arguments, 1 provided| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|656|note: candidate: std::basic_ofstream<char>::basic_ofstream(const std::basic_ofstream<char>&)| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\fstream|656|note: no known conversion for argument 1 from 'const string {aka const std::__cxx11::basic_string<char>}' to 'const std::basic_ofstream<char>&'| D:\1.cpp|88|warning: range-based 'for' loops only available with -std=c++11 or -std=gnu++11| D:\1.cpp|89|error: request for member 'name' in 's', which is of non-class type 'const int'| D:\1.cpp|89|error: 'grade' was not declared in this scope| D:\1.cpp||In member function 'bool GradeManager::modify_student(const string&)':| D:\1.cpp|98|warning: range-based 'for' loops only available with -std=c++11 or -std=gnu++11| D:\1.cpp|99|error: request for member 'name' in 's', which is of non-class type 'int'| D:\1.cpp|101|error: request for member 'read' in 's', which is of non-class type 'int'| D:\1.cpp||In member function 'bool GradeManager::delete_student(const string&)':| D:\1.cpp|109|error: 'it' does not name a type| D:\1.cpp|110|error: expected primary-expression before ')' token| D:\1.cpp|112|error: 'it' was not declared in this scope| D:\1.cpp||In member function 'Student_info* GradeManager::find_student(const string&)':| D:\1.cpp|120|warning: range-based 'for' loops only available with -std=c++11 or -std=gnu++11| D:\1.cpp|121|error: request for member 'name' in 's', which is of non-class type 'int'| D:\1.cpp|122|error: cannot convert 'int*' to 'Student_info*' in return| D:\1.cpp|125|error: 'nullptr' was not declared in this scope| D:\1.cpp|13|error: 'std::__cxx11::string Student_info::name' is private| D:\1.cpp|131|error: within this context| D:\1.cpp||In member function 'void GradeManager::sort_by_name()':| D:\1.cpp|132|warning: lambda expressions only available with -std=c++11 or -std=gnu++11| D:\1.cpp|132|error: no matching function for call to 'sort(std::vector<Student_info>::iterator, std::vector<Student_info>::iterator, GradeManager::sort_by_name()::<lambda(const Student_info&, const Student_info&)>)'| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\stl_algo.h|4689|note: candidate: template<class _RAIter> void std::sort(_RAIter, _RAIter)| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\stl_algo.h|4689|note: template argument deduction/substitution failed:| D:\1.cpp|132|note: candidate expects 2 arguments, 3 provided| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\stl_algo.h|4718|note: candidate: template<class _RAIter, class _Compare> void std::sort(_RAIter, _RAIter, _Compare)| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\stl_algo.h|4718|note: template argument deduction/substitution failed:| D:\1.cpp|132|required from here| D:\1.cpp|132|error: template argument for 'template<class _RAIter, class _Compare> void std::sort(_RAIter, _RAIter, _Compare)' uses local type 'GradeManager::sort_by_name()::<lambda(const Student_info&, const Student_info&)>'| D:\1.cpp|132|error: trying to instantiate 'template<class _RAIter, class _Compare> void std::sort(_RAIter, _RAIter, _Compare)'| D:\1.cpp|138|error: 'grade' was not declared in this scope| D:\1.cpp||In member function 'void GradeManager::sort_by_grade()':| D:\1.cpp|139|warning: lambda expressions only available with -std=c++11 or -std=gnu++11| D:\1.cpp|139|error: no matching function for call to 'sort(std::vector<Student_info>::iterator, std::vector<Student_info>::iterator, GradeManager::sort_by_grade()::<lambda(const Student_info&, const Student_info&)>)'| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\stl_algo.h|4689|note: candidate: template<class _RAIter> void std::sort(_RAIter, _RAIter)| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\stl_algo.h|4689|note: template argument deduction/substitution failed:| D:\1.cpp|139|note: candidate expects 2 arguments, 3 provided| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\stl_algo.h|4718|note: candidate: template<class _RAIter, class _Compare> void std::sort(_RAIter, _RAIter, _Compare)| D:\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\stl_algo.h|4718|note: template argument deduction/substitution failed:| D:\1.cpp|139|required from here| D:\1.cpp|139|error: template argument for 'template<class _RAIter, class _Compare> void std::sort(_RAIter, _RAIter, _Compare)' uses local type 'GradeManager::sort_by_grade()::<lambda(const Student_info&, const Student_info&)>'| D:\1.cpp|139|error: trying to instantiate 'template<class _RAIter, class _Compare> void std::sort(_RAIter, _RAIter, _Compare)'| D:\1.cpp||In member function 'void GradeManager::display_all()':| D:\1.cpp|143|warning: range-based 'for' loops only available with -std=c++11 or -std=gnu++11| D:\1.cpp|144|error: request for member 'name' in 's', which is of non-class type 'const int'| D:\1.cpp|144|error: 'grade' was not declared in this scope| D:\1.cpp||In function 'int main()':| D:\1.cpp|13|error: 'std::__cxx11::string Student_info::name' is private| D:\1.cpp|182|error: within this context| D:\1.cpp|182|error: 'grade' was not declared in this scope| ||=== Build failed: 27 error(s), 8 warning(s) (0 minute(s), 1 second(s)) ===|
06-19
// Core algorithmic facilities -*- C++ -*- // Copyright (C) 2001-2014 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // <http://www.gnu.org/licenses/>. /* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Hewlett-Packard Company makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * * * Copyright (c) 1996-1998 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ /** @file bits/stl_algobase.h * This is an internal header file, included by other library headers. * Do not attempt to use it directly. @headername{algorithm} */ #ifndef _STL_ALGOBASE_H #define _STL_ALGOBASE_H 1 #include <bits/c++config.h> #include <bits/functexcept.h> #include <bits/cpp_type_traits.h> #include <ext/type_traits.h> #include <ext/numeric_traits.h> #include <bits/stl_pair.h> #include <bits/stl_iterator_base_types.h> #include <bits/stl_iterator_base_funcs.h> #include <bits/stl_iterator.h> #include <bits/concept_check.h> #include <debug/debug.h> #include <bits/move.h> // For std::swap and _GLIBCXX_MOVE #include <bits/predefined_ops.h> namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus < 201103L // See http://gcc.gnu.org/ml/libstdc++/2004-08/msg00167.html: in a // nutshell, we are partially implementing the resolution of DR 187, // when it's safe, i.e., the value_types are equal. template<bool _BoolType> struct __iter_swap { template<typename _ForwardIterator1, typename _ForwardIterator2> static void iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) { typedef typename iterator_traits<_ForwardIterator1>::value_type _ValueType1; _ValueType1 __tmp = _GLIBCXX_MOVE(*__a); *__a = _GLIBCXX_MOVE(*__b); *__b = _GLIBCXX_MOVE(__tmp); } }; template<> struct __iter_swap<true> { template<typename _ForwardIterator1, typename _ForwardIterator2> static void iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) { swap(*__a, *__b); } }; #endif /** * @brief Swaps the contents of two iterators. * @ingroup mutating_algorithms * @param __a An iterator. * @param __b Another iterator. * @return Nothing. * * This function swaps the values pointed to by two iterators, not the * iterators themselves. */ template<typename _ForwardIterator1, typename _ForwardIterator2> inline void iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) { // concept requirements __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< _ForwardIterator1>) __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< _ForwardIterator2>) #if __cplusplus < 201103L typedef typename iterator_traits<_ForwardIterator1>::value_type _ValueType1; typedef typename iterator_traits<_ForwardIterator2>::value_type _ValueType2; __glibcxx_function_requires(_ConvertibleConcept<_ValueType1, _ValueType2>) __glibcxx_function_requires(_ConvertibleConcept<_ValueType2, _ValueType1>) typedef typename iterator_traits<_ForwardIterator1>::reference _ReferenceType1; typedef typename iterator_traits<_ForwardIterator2>::reference _ReferenceType2; std::__iter_swap<__are_same<_ValueType1, _ValueType2>::__value && __are_same<_ValueType1&, _ReferenceType1>::__value && __are_same<_ValueType2&, _ReferenceType2>::__value>:: iter_swap(__a, __b); #else swap(*__a, *__b); #endif } /** * @brief Swap the elements of two sequences. * @ingroup mutating_algorithms * @param __first1 A forward iterator. * @param __last1 A forward iterator. * @param __first2 A forward iterator. * @return An iterator equal to @p first2+(last1-first1). * * Swaps each element in the range @p [first1,last1) with the * corresponding element in the range @p [first2,(last1-first1)). * The ranges must not overlap. */ template<typename _ForwardIterator1, typename _ForwardIterator2> _ForwardIterator2 swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { // concept requirements __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< _ForwardIterator1>) __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< _ForwardIterator2>) __glibcxx_requires_valid_range(__first1, __last1); for (; __first1 != __last1; ++__first1, ++__first2) std::iter_swap(__first1, __first2); return __first2; } /** * @brief This does what you think it does. * @ingroup sorting_algorithms * @param __a A thing of arbitrary type. * @param __b Another thing of arbitrary type. * @return The lesser of the parameters. * * This is the simple classic generic implementation. It will work on * temporary expressions, since they are only evaluated once, unlike a * preprocessor macro. */ template<typename _Tp> inline const _Tp& min(const _Tp& __a, const _Tp& __b) { // concept requirements __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) //return __b < __a ? __b : __a; if (__b < __a) return __b; return __a; } /** * @brief This does what you think it does. * @ingroup sorting_algorithms * @param __a A thing of arbitrary type. * @param __b Another thing of arbitrary type. * @return The greater of the parameters. * * This is the simple classic generic implementation. It will work on * temporary expressions, since they are only evaluated once, unlike a * preprocessor macro. */ template<typename _Tp> inline const _Tp& max(const _Tp& __a, const _Tp& __b) { // concept requirements __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) //return __a < __b ? __b : __a; if (__a < __b) return __b; return __a; } /** * @brief This does what you think it does. * @ingroup sorting_algorithms * @param __a A thing of arbitrary type. * @param __b Another thing of arbitrary type. * @param __comp A @link comparison_functors comparison functor@endlink. * @return The lesser of the parameters. * * This will work on temporary expressions, since they are only evaluated * once, unlike a preprocessor macro. */ template<typename _Tp, typename _Compare> inline const _Tp& min(const _Tp& __a, const _Tp& __b, _Compare __comp) { //return __comp(__b, __a) ? __b : __a; if (__comp(__b, __a)) return __b; return __a; } /** * @brief This does what you think it does. * @ingroup sorting_algorithms * @param __a A thing of arbitrary type. * @param __b Another thing of arbitrary type. * @param __comp A @link comparison_functors comparison functor@endlink. * @return The greater of the parameters. * * This will work on temporary expressions, since they are only evaluated * once, unlike a preprocessor macro. */ template<typename _Tp, typename _Compare> inline const _Tp& max(const _Tp& __a, const _Tp& __b, _Compare __comp) { //return __comp(__a, __b) ? __b : __a; if (__comp(__a, __b)) return __b; return __a; } // If _Iterator is a __normal_iterator return its base (a plain pointer, // normally) otherwise return it untouched. See copy, fill, ... template<typename _Iterator> struct _Niter_base : _Iter_base<_Iterator, __is_normal_iterator<_Iterator>::__value> { }; template<typename _Iterator> inline typename _Niter_base<_Iterator>::iterator_type __niter_base(_Iterator __it) { return std::_Niter_base<_Iterator>::_S_base(__it); } // Likewise, for move_iterator. template<typename _Iterator> struct _Miter_base : _Iter_base<_Iterator, __is_move_iterator<_Iterator>::__value> { }; template<typename _Iterator> inline typename _Miter_base<_Iterator>::iterator_type __miter_base(_Iterator __it) { return std::_Miter_base<_Iterator>::_S_base(__it); } // All of these auxiliary structs serve two purposes. (1) Replace // calls to copy with memmove whenever possible. (Memmove, not memcpy, // because the input and output ranges are permitted to overlap.) // (2) If we're using random access iterators, then write the loop as // a for loop with an explicit count. template<bool, bool, typename> struct __copy_move { template<typename _II, typename _OI> static _OI __copy_m(_II __first, _II __last, _OI __result) { for (; __first != __last; ++__result, ++__first) *__result = *__first; return __result; } }; #if __cplusplus >= 201103L template<typename _Category> struct __copy_move<true, false, _Category> { template<typename _II, typename _OI> static _OI __copy_m(_II __first, _II __last, _OI __result) { for (; __first != __last; ++__result, ++__first) *__result = std::move(*__first); return __result; } }; #endif template<> struct __copy_move<false, false, random_access_iterator_tag> { template<typename _II, typename _OI> static _OI __copy_m(_II __first, _II __last, _OI __result) { typedef typename iterator_traits<_II>::difference_type _Distance; for(_Distance __n = __last - __first; __n > 0; --__n) { *__result = *__first; ++__first; ++__result; } return __result; } }; #if __cplusplus >= 201103L template<> struct __copy_move<true, false, random_access_iterator_tag> { template<typename _II, typename _OI> static _OI __copy_m(_II __first, _II __last, _OI __result) { typedef typename iterator_traits<_II>::difference_type _Distance; for(_Distance __n = __last - __first; __n > 0; --__n) { *__result = std::move(*__first); ++__first; ++__result; } return __result; } }; #endif template<bool _IsMove> struct __copy_move<_IsMove, true, random_access_iterator_tag> { template<typename _Tp> static _Tp* __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result) { #if __cplusplus >= 201103L // trivial types can have deleted assignment static_assert( is_copy_assignable<_Tp>::value, "type is not assignable" ); #endif const ptrdiff_t _Num = __last - __first; if (_Num) __builtin_memmove(__result, __first, sizeof(_Tp) * _Num); return __result + _Num; } }; template<bool _IsMove, typename _II, typename _OI> inline _OI __copy_move_a(_II __first, _II __last, _OI __result) { typedef typename iterator_traits<_II>::value_type _ValueTypeI; typedef typename iterator_traits<_OI>::value_type _ValueTypeO; typedef typename iterator_traits<_II>::iterator_category _Category; const bool __simple = (__is_trivial(_ValueTypeI) && __is_pointer<_II>::__value && __is_pointer<_OI>::__value && __are_same<_ValueTypeI, _ValueTypeO>::__value); return std::__copy_move<_IsMove, __simple, _Category>::__copy_m(__first, __last, __result); } // Helpers for streambuf iterators (either istream or ostream). // NB: avoid including <iosfwd>, relatively large. template<typename _CharT> struct char_traits; template<typename _CharT, typename _Traits> class istreambuf_iterator; template<typename _CharT, typename _Traits> class ostreambuf_iterator; template<bool _IsMove, typename _CharT> typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, ostreambuf_iterator<_CharT, char_traits<_CharT> > >::__type __copy_move_a2(_CharT*, _CharT*, ostreambuf_iterator<_CharT, char_traits<_CharT> >); template<bool _IsMove, typename _CharT> typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, ostreambuf_iterator<_CharT, char_traits<_CharT> > >::__type __copy_move_a2(const _CharT*, const _CharT*, ostreambuf_iterator<_CharT, char_traits<_CharT> >); template<bool _IsMove, typename _CharT> typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, _CharT*>::__type __copy_move_a2(istreambuf_iterator<_CharT, char_traits<_CharT> >, istreambuf_iterator<_CharT, char_traits<_CharT> >, _CharT*); template<bool _IsMove, typename _II, typename _OI> inline _OI __copy_move_a2(_II __first, _II __last, _OI __result) { return _OI(std::__copy_move_a<_IsMove>(std::__niter_base(__first), std::__niter_base(__last), std::__niter_base(__result))); } /** * @brief Copies the range [first,last) into result. * @ingroup mutating_algorithms * @param __first An input iterator. * @param __last An input iterator. * @param __result An output iterator. * @return result + (first - last) * * This inline function will boil down to a call to @c memmove whenever * possible. Failing that, if random access iterators are passed, then the * loop count will be known (and therefore a candidate for compiler * optimizations such as unrolling). Result may not be contained within * [first,last); the copy_backward function should be used instead. * * Note that the end of the output range is permitted to be contained * within [first,last). */ template<typename _II, typename _OI> inline _OI copy(_II __first, _II __last, _OI __result) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_II>) __glibcxx_function_requires(_OutputIteratorConcept<_OI, typename iterator_traits<_II>::value_type>) __glibcxx_requires_valid_range(__first, __last); return (std::__copy_move_a2<__is_move_iterator<_II>::__value> (std::__miter_base(__first), std::__miter_base(__last), __result)); } #if __cplusplus >= 201103L /** * @brief Moves the range [first,last) into result. * @ingroup mutating_algorithms * @param __first An input iterator. * @param __last An input iterator. * @param __result An output iterator. * @return result + (first - last) * * This inline function will boil down to a call to @c memmove whenever * possible. Failing that, if random access iterators are passed, then the * loop count will be known (and therefore a candidate for compiler * optimizations such as unrolling). Result may not be contained within * [first,last); the move_backward function should be used instead. * * Note that the end of the output range is permitted to be contained * within [first,last). */ template<typename _II, typename _OI> inline _OI move(_II __first, _II __last, _OI __result) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_II>) __glibcxx_function_requires(_OutputIteratorConcept<_OI, typename iterator_traits<_II>::value_type>) __glibcxx_requires_valid_range(__first, __last); return std::__copy_move_a2<true>(std::__miter_base(__first), std::__miter_base(__last), __result); } #define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::move(_Tp, _Up, _Vp) #else #define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::copy(_Tp, _Up, _Vp) #endif template<bool, bool, typename> struct __copy_move_backward { template<typename _BI1, typename _BI2> static _BI2 __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) { while (__first != __last) *--__result = *--__last; return __result; } }; #if __cplusplus >= 201103L template<typename _Category> struct __copy_move_backward<true, false, _Category> { template<typename _BI1, typename _BI2> static _BI2 __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) { while (__first != __last) *--__result = std::move(*--__last); return __result; } }; #endif template<> struct __copy_move_backward<false, false, random_access_iterator_tag> { template<typename _BI1, typename _BI2> static _BI2 __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) { typename iterator_traits<_BI1>::difference_type __n; for (__n = __last - __first; __n > 0; --__n) *--__result = *--__last; return __result; } }; #if __cplusplus >= 201103L template<> struct __copy_move_backward<true, false, random_access_iterator_tag> { template<typename _BI1, typename _BI2> static _BI2 __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) { typename iterator_traits<_BI1>::difference_type __n; for (__n = __last - __first; __n > 0; --__n) *--__result = std::move(*--__last); return __result; } }; #endif template<bool _IsMove> struct __copy_move_backward<_IsMove, true, random_access_iterator_tag> { template<typename _Tp> static _Tp* __copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result) { #if __cplusplus >= 201103L // trivial types can have deleted assignment static_assert( is_copy_assignable<_Tp>::value, "type is not assignable" ); #endif const ptrdiff_t _Num = __last - __first; if (_Num) __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num); return __result - _Num; } }; template<bool _IsMove, typename _BI1, typename _BI2> inline _BI2 __copy_move_backward_a(_BI1 __first, _BI1 __last, _BI2 __result) { typedef typename iterator_traits<_BI1>::value_type _ValueType1; typedef typename iterator_traits<_BI2>::value_type _ValueType2; typedef typename iterator_traits<_BI1>::iterator_category _Category; const bool __simple = (__is_trivial(_ValueType1) && __is_pointer<_BI1>::__value && __is_pointer<_BI2>::__value && __are_same<_ValueType1, _ValueType2>::__value); return std::__copy_move_backward<_IsMove, __simple, _Category>::__copy_move_b(__first, __last, __result); } template<bool _IsMove, typename _BI1, typename _BI2> inline _BI2 __copy_move_backward_a2(_BI1 __first, _BI1 __last, _BI2 __result) { return _BI2(std::__copy_move_backward_a<_IsMove> (std::__niter_base(__first), std::__niter_base(__last), std::__niter_base(__result))); } /** * @brief Copies the range [first,last) into result. * @ingroup mutating_algorithms * @param __first A bidirectional iterator. * @param __last A bidirectional iterator. * @param __result A bidirectional iterator. * @return result - (first - last) * * The function has the same effect as copy, but starts at the end of the * range and works its way to the start, returning the start of the result. * This inline function will boil down to a call to @c memmove whenever * possible. Failing that, if random access iterators are passed, then the * loop count will be known (and therefore a candidate for compiler * optimizations such as unrolling). * * Result may not be in the range (first,last]. Use copy instead. Note * that the start of the output range may overlap [first,last). */ template<typename _BI1, typename _BI2> inline _BI2 copy_backward(_BI1 __first, _BI1 __last, _BI2 __result) { // concept requirements __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) __glibcxx_function_requires(_ConvertibleConcept< typename iterator_traits<_BI1>::value_type, typename iterator_traits<_BI2>::value_type>) __glibcxx_requires_valid_range(__first, __last); return (std::__copy_move_backward_a2<__is_move_iterator<_BI1>::__value> (std::__miter_base(__first), std::__miter_base(__last), __result)); } #if __cplusplus >= 201103L /** * @brief Moves the range [first,last) into result. * @ingroup mutating_algorithms * @param __first A bidirectional iterator. * @param __last A bidirectional iterator. * @param __result A bidirectional iterator. * @return result - (first - last) * * The function has the same effect as move, but starts at the end of the * range and works its way to the start, returning the start of the result. * This inline function will boil down to a call to @c memmove whenever * possible. Failing that, if random access iterators are passed, then the * loop count will be known (and therefore a candidate for compiler * optimizations such as unrolling). * * Result may not be in the range (first,last]. Use move instead. Note * that the start of the output range may overlap [first,last). */ template<typename _BI1, typename _BI2> inline _BI2 move_backward(_BI1 __first, _BI1 __last, _BI2 __result) { // concept requirements __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) __glibcxx_function_requires(_ConvertibleConcept< typename iterator_traits<_BI1>::value_type, typename iterator_traits<_BI2>::value_type>) __glibcxx_requires_valid_range(__first, __last); return std::__copy_move_backward_a2<true>(std::__miter_base(__first), std::__miter_base(__last), __result); } #define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::move_backward(_Tp, _Up, _Vp) #else #define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::copy_backward(_Tp, _Up, _Vp) #endif template<typename _ForwardIterator, typename _Tp> inline typename __gnu_cxx::__enable_if<!__is_scalar<_Tp>::__value, void>::__type __fill_a(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { for (; __first != __last; ++__first) *__first = __value; } template<typename _ForwardIterator, typename _Tp> inline typename __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, void>::__type __fill_a(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { const _Tp __tmp = __value; for (; __first != __last; ++__first) *__first = __tmp; } // Specialization: for char types we can use memset. template<typename _Tp> inline typename __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, void>::__type __fill_a(_Tp* __first, _Tp* __last, const _Tp& __c) { const _Tp __tmp = __c; __builtin_memset(__first, static_cast<unsigned char>(__tmp), __last - __first); } /** * @brief Fills the range [first,last) with copies of value. * @ingroup mutating_algorithms * @param __first A forward iterator. * @param __last A forward iterator. * @param __value A reference-to-const of arbitrary type. * @return Nothing. * * This function fills a range with copies of the same value. For char * types filling contiguous areas of memory, this becomes an inline call * to @c memset or @c wmemset. */ template<typename _ForwardIterator, typename _Tp> inline void fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { // concept requirements __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< _ForwardIterator>) __glibcxx_requires_valid_range(__first, __last); std::__fill_a(std::__niter_base(__first), std::__niter_base(__last), __value); } template<typename _OutputIterator, typename _Size, typename _Tp> inline typename __gnu_cxx::__enable_if<!__is_scalar<_Tp>::__value, _OutputIterator>::__type __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value) { for (__decltype(__n + 0) __niter = __n; __niter > 0; --__niter, ++__first) *__first = __value; return __first; } template<typename _OutputIterator, typename _Size, typename _Tp> inline typename __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, _OutputIterator>::__type __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value) { const _Tp __tmp = __value; for (__decltype(__n + 0) __niter = __n; __niter > 0; --__niter, ++__first) *__first = __tmp; return __first; } template<typename _Size, typename _Tp> inline typename __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, _Tp*>::__type __fill_n_a(_Tp* __first, _Size __n, const _Tp& __c) { std::__fill_a(__first, __first + __n, __c); return __first + __n; } /** * @brief Fills the range [first,first+n) with copies of value. * @ingroup mutating_algorithms * @param __first An output iterator. * @param __n The count of copies to perform. * @param __value A reference-to-const of arbitrary type. * @return The iterator at first+n. * * This function fills a range with copies of the same value. For char * types filling contiguous areas of memory, this becomes an inline call * to @c memset or @ wmemset. * * _GLIBCXX_RESOLVE_LIB_DEFECTS * DR 865. More algorithms that throw away information */ template<typename _OI, typename _Size, typename _Tp> inline _OI fill_n(_OI __first, _Size __n, const _Tp& __value) { // concept requirements __glibcxx_function_requires(_OutputIteratorConcept<_OI, _Tp>) return _OI(std::__fill_n_a(std::__niter_base(__first), __n, __value)); } template<bool _BoolType> struct __equal { template<typename _II1, typename _II2> static bool equal(_II1 __first1, _II1 __last1, _II2 __first2) { for (; __first1 != __last1; ++__first1, ++__first2) if (!(*__first1 == *__first2)) return false; return true; } }; template<> struct __equal<true> { template<typename _Tp> static bool equal(const _Tp* __first1, const _Tp* __last1, const _Tp* __first2) { return !__builtin_memcmp(__first1, __first2, sizeof(_Tp) * (__last1 - __first1)); } }; template<typename _II1, typename _II2> inline bool __equal_aux(_II1 __first1, _II1 __last1, _II2 __first2) { typedef typename iterator_traits<_II1>::value_type _ValueType1; typedef typename iterator_traits<_II2>::value_type _ValueType2; const bool __simple = ((__is_integer<_ValueType1>::__value || __is_pointer<_ValueType1>::__value) && __is_pointer<_II1>::__value && __is_pointer<_II2>::__value && __are_same<_ValueType1, _ValueType2>::__value); return std::__equal<__simple>::equal(__first1, __last1, __first2); } template<typename, typename> struct __lc_rai { template<typename _II1, typename _II2> static _II1 __newlast1(_II1, _II1 __last1, _II2, _II2) { return __last1; } template<typename _II> static bool __cnd2(_II __first, _II __last) { return __first != __last; } }; template<> struct __lc_rai<random_access_iterator_tag, random_access_iterator_tag> { template<typename _RAI1, typename _RAI2> static _RAI1 __newlast1(_RAI1 __first1, _RAI1 __last1, _RAI2 __first2, _RAI2 __last2) { const typename iterator_traits<_RAI1>::difference_type __diff1 = __last1 - __first1; const typename iterator_traits<_RAI2>::difference_type __diff2 = __last2 - __first2; return __diff2 < __diff1 ? __first1 + __diff2 : __last1; } template<typename _RAI> static bool __cnd2(_RAI, _RAI) { return true; } }; template<typename _II1, typename _II2, typename _Compare> bool __lexicographical_compare_impl(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2, _Compare __comp) { typedef typename iterator_traits<_II1>::iterator_category _Category1; typedef typename iterator_traits<_II2>::iterator_category _Category2; typedef std::__lc_rai<_Category1, _Category2> __rai_type; __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2); for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2); ++__first1, ++__first2) { if (__comp(__first1, __first2)) return true; if (__comp(__first2, __first1)) return false; } return __first1 == __last1 && __first2 != __last2; } template<bool _BoolType> struct __lexicographical_compare { template<typename _II1, typename _II2> static bool __lc(_II1, _II1, _II2, _II2); }; template<bool _BoolType> template<typename _II1, typename _II2> bool __lexicographical_compare<_BoolType>:: __lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) { return std::__lexicographical_compare_impl(__first1, __last1, __first2, __last2, __gnu_cxx::__ops::__iter_less_iter()); } template<> struct __lexicographical_compare<true> { template<typename _Tp, typename _Up> static bool __lc(const _Tp* __first1, const _Tp* __last1, const _Up* __first2, const _Up* __last2) { const size_t __len1 = __last1 - __first1; const size_t __len2 = __last2 - __first2; const int __result = __builtin_memcmp(__first1, __first2, std::min(__len1, __len2)); return __result != 0 ? __result < 0 : __len1 < __len2; } }; template<typename _II1, typename _II2> inline bool __lexicographical_compare_aux(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) { typedef typename iterator_traits<_II1>::value_type _ValueType1; typedef typename iterator_traits<_II2>::value_type _ValueType2; const bool __simple = (__is_byte<_ValueType1>::__value && __is_byte<_ValueType2>::__value && !__gnu_cxx::__numeric_traits<_ValueType1>::__is_signed && !__gnu_cxx::__numeric_traits<_ValueType2>::__is_signed && __is_pointer<_II1>::__value && __is_pointer<_II2>::__value); return std::__lexicographical_compare<__simple>::__lc(__first1, __last1, __first2, __last2); } template<typename _ForwardIterator, typename _Tp, typename _Compare> _ForwardIterator __lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __val, _Compare __comp) { typedef typename iterator_traits<_ForwardIterator>::difference_type _DistanceType; _DistanceType __len = std::distance(__first, __last); while (__len > 0) { _DistanceType __half = __len >> 1; _ForwardIterator __middle = __first; std::advance(__middle, __half); if (__comp(__middle, __val)) { __first = __middle; ++__first; __len = __len - __half - 1; } else __len = __half; } return __first; } /** * @brief Finds the first position in which @a val could be inserted * without changing the ordering. * @param __first An iterator. * @param __last Another iterator. * @param __val The search term. * @return An iterator pointing to the first element <em>not less * than</em> @a val, or end() if every element is less than * @a val. * @ingroup binary_search_algorithms */ template<typename _ForwardIterator, typename _Tp> inline _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __val) { // concept requirements __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) __glibcxx_function_requires(_LessThanOpConcept< typename iterator_traits<_ForwardIterator>::value_type, _Tp>) __glibcxx_requires_partitioned_lower(__first, __last, __val); return std::__lower_bound(__first, __last, __val, __gnu_cxx::__ops::__iter_less_val()); } /// This is a helper function for the sort routines and for random.tcc. // Precondition: __n > 0. inline _GLIBCXX_CONSTEXPR int __lg(int __n) { return sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } inline _GLIBCXX_CONSTEXPR unsigned __lg(unsigned __n) { return sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } inline _GLIBCXX_CONSTEXPR long __lg(long __n) { return sizeof(long) * __CHAR_BIT__ - 1 - __builtin_clzl(__n); } inline _GLIBCXX_CONSTEXPR unsigned long __lg(unsigned long __n) { return sizeof(long) * __CHAR_BIT__ - 1 - __builtin_clzl(__n); } inline _GLIBCXX_CONSTEXPR long long __lg(long long __n) { return sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); } inline _GLIBCXX_CONSTEXPR unsigned long long __lg(unsigned long long __n) { return sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); } _GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_ALGO /** * @brief Tests a range for element-wise equality. * @ingroup non_mutating_algorithms * @param __first1 An input iterator. * @param __last1 An input iterator. * @param __first2 An input iterator. * @return A boolean true or false. * * This compares the elements of two ranges using @c == and returns true or * false depending on whether all of the corresponding elements of the * ranges are equal. */ template<typename _II1, typename _II2> inline bool equal(_II1 __first1, _II1 __last1, _II2 __first2) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_II1>) __glibcxx_function_requires(_InputIteratorConcept<_II2>) __glibcxx_function_requires(_EqualOpConcept< typename iterator_traits<_II1>::value_type, typename iterator_traits<_II2>::value_type>) __glibcxx_requires_valid_range(__first1, __last1); return std::__equal_aux(std::__niter_base(__first1), std::__niter_base(__last1), std::__niter_base(__first2)); } /** * @brief Tests a range for element-wise equality. * @ingroup non_mutating_algorithms * @param __first1 An input iterator. * @param __last1 An input iterator. * @param __first2 An input iterator. * @param __binary_pred A binary predicate @link functors * functor@endlink. * @return A boolean true or false. * * This compares the elements of two ranges using the binary_pred * parameter, and returns true or * false depending on whether all of the corresponding elements of the * ranges are equal. */ template<typename _IIter1, typename _IIter2, typename _BinaryPredicate> inline bool equal(_IIter1 __first1, _IIter1 __last1, _IIter2 __first2, _BinaryPredicate __binary_pred) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) __glibcxx_requires_valid_range(__first1, __last1); for (; __first1 != __last1; ++__first1, ++__first2) if (!bool(__binary_pred(*__first1, *__first2))) return false; return true; } #if __cplusplus > 201103L #define __cpp_lib_robust_nonmodifying_seq_ops 201304 /** * @brief Tests a range for element-wise equality. * @ingroup non_mutating_algorithms * @param __first1 An input iterator. * @param __last1 An input iterator. * @param __first2 An input iterator. * @param __last2 An input iterator. * @return A boolean true or false. * * This compares the elements of two ranges using @c == and returns true or * false depending on whether all of the corresponding elements of the * ranges are equal. */ template<typename _II1, typename _II2> inline bool equal(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_II1>) __glibcxx_function_requires(_InputIteratorConcept<_II2>) __glibcxx_function_requires(_EqualOpConcept< typename iterator_traits<_II1>::value_type, typename iterator_traits<_II2>::value_type>) __glibcxx_requires_valid_range(__first1, __last1); __glibcxx_requires_valid_range(__first2, __last2); using _RATag = random_access_iterator_tag; using _Cat1 = typename iterator_traits<_II1>::iterator_category; using _Cat2 = typename iterator_traits<_II2>::iterator_category; using _RAIters = __and_<is_same<_Cat1, _RATag>, is_same<_Cat2, _RATag>>; if (_RAIters()) { auto __d1 = std::distance(__first1, __last1); auto __d2 = std::distance(__first2, __last2); if (__d1 != __d2) return false; return _GLIBCXX_STD_A::equal(__first1, __last1, __first2); } for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2) if (!(*__first1 == *__first2)) return false; return __first1 == __last1 && __first2 == __last2; } /** * @brief Tests a range for element-wise equality. * @ingroup non_mutating_algorithms * @param __first1 An input iterator. * @param __last1 An input iterator. * @param __first2 An input iterator. * @param __last2 An input iterator. * @param __binary_pred A binary predicate @link functors * functor@endlink. * @return A boolean true or false. * * This compares the elements of two ranges using the binary_pred * parameter, and returns true or * false depending on whether all of the corresponding elements of the * ranges are equal. */ template<typename _IIter1, typename _IIter2, typename _BinaryPredicate> inline bool equal(_IIter1 __first1, _IIter1 __last1, _IIter2 __first2, _IIter2 __last2, _BinaryPredicate __binary_pred) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) __glibcxx_requires_valid_range(__first1, __last1); __glibcxx_requires_valid_range(__first2, __last2); using _RATag = random_access_iterator_tag; using _Cat1 = typename iterator_traits<_IIter1>::iterator_category; using _Cat2 = typename iterator_traits<_IIter2>::iterator_category; using _RAIters = __and_<is_same<_Cat1, _RATag>, is_same<_Cat2, _RATag>>; if (_RAIters()) { auto __d1 = std::distance(__first1, __last1); auto __d2 = std::distance(__first2, __last2); if (__d1 != __d2) return false; return _GLIBCXX_STD_A::equal(__first1, __last1, __first2, __binary_pred); } for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2) if (!bool(__binary_pred(*__first1, *__first2))) return false; return __first1 == __last1 && __first2 == __last2; } #endif /** * @brief Performs @b dictionary comparison on ranges. * @ingroup sorting_algorithms * @param __first1 An input iterator. * @param __last1 An input iterator. * @param __first2 An input iterator. * @param __last2 An input iterator. * @return A boolean true or false. * * <em>Returns true if the sequence of elements defined by the range * [first1,last1) is lexicographically less than the sequence of elements * defined by the range [first2,last2). Returns false otherwise.</em> * (Quoted from [25.3.8]/1.) If the iterators are all character pointers, * then this is an inline call to @c memcmp. */ template<typename _II1, typename _II2> inline bool lexicographical_compare(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) { #ifdef _GLIBCXX_CONCEPT_CHECKS // concept requirements typedef typename iterator_traits<_II1>::value_type _ValueType1; typedef typename iterator_traits<_II2>::value_type _ValueType2; #endif __glibcxx_function_requires(_InputIteratorConcept<_II1>) __glibcxx_function_requires(_InputIteratorConcept<_II2>) __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>) __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>) __glibcxx_requires_valid_range(__first1, __last1); __glibcxx_requires_valid_range(__first2, __last2); return std::__lexicographical_compare_aux(std::__niter_base(__first1), std::__niter_base(__last1), std::__niter_base(__first2), std::__niter_base(__last2)); } /** * @brief Performs @b dictionary comparison on ranges. * @ingroup sorting_algorithms * @param __first1 An input iterator. * @param __last1 An input iterator. * @param __first2 An input iterator. * @param __last2 An input iterator. * @param __comp A @link comparison_functors comparison functor@endlink. * @return A boolean true or false. * * The same as the four-parameter @c lexicographical_compare, but uses the * comp parameter instead of @c <. */ template<typename _II1, typename _II2, typename _Compare> inline bool lexicographical_compare(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2, _Compare __comp) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_II1>) __glibcxx_function_requires(_InputIteratorConcept<_II2>) __glibcxx_requires_valid_range(__first1, __last1); __glibcxx_requires_valid_range(__first2, __last2); return std::__lexicographical_compare_impl (__first1, __last1, __first2, __last2, __gnu_cxx::__ops::__iter_comp_iter(__comp)); } template<typename _InputIterator1, typename _InputIterator2, typename _BinaryPredicate> pair<_InputIterator1, _InputIterator2> __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __binary_pred) { while (__first1 != __last1 && __binary_pred(__first1, __first2)) { ++__first1; ++__first2; } return pair<_InputIterator1, _InputIterator2>(__first1, __first2); } /** * @brief Finds the places in ranges which don't match. * @ingroup non_mutating_algorithms * @param __first1 An input iterator. * @param __last1 An input iterator. * @param __first2 An input iterator. * @return A pair of iterators pointing to the first mismatch. * * This compares the elements of two ranges using @c == and returns a pair * of iterators. The first iterator points into the first range, the * second iterator points into the second range, and the elements pointed * to by the iterators are not equal. */ template<typename _InputIterator1, typename _InputIterator2> inline pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) __glibcxx_function_requires(_EqualOpConcept< typename iterator_traits<_InputIterator1>::value_type, typename iterator_traits<_InputIterator2>::value_type>) __glibcxx_requires_valid_range(__first1, __last1); return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __gnu_cxx::__ops::__iter_equal_to_iter()); } /** * @brief Finds the places in ranges which don't match. * @ingroup non_mutating_algorithms * @param __first1 An input iterator. * @param __last1 An input iterator. * @param __first2 An input iterator. * @param __binary_pred A binary predicate @link functors * functor@endlink. * @return A pair of iterators pointing to the first mismatch. * * This compares the elements of two ranges using the binary_pred * parameter, and returns a pair * of iterators. The first iterator points into the first range, the * second iterator points into the second range, and the elements pointed * to by the iterators are not equal. */ template<typename _InputIterator1, typename _InputIterator2, typename _BinaryPredicate> inline pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __binary_pred) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) __glibcxx_requires_valid_range(__first1, __last1); return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); } #if __cplusplus > 201103L template<typename _InputIterator1, typename _InputIterator2, typename _BinaryPredicate> pair<_InputIterator1, _InputIterator2> __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _BinaryPredicate __binary_pred) { while (__first1 != __last1 && __first2 != __last2 && __binary_pred(__first1, __first2)) { ++__first1; ++__first2; } return pair<_InputIterator1, _InputIterator2>(__first1, __first2); } /** * @brief Finds the places in ranges which don't match. * @ingroup non_mutating_algorithms * @param __first1 An input iterator. * @param __last1 An input iterator. * @param __first2 An input iterator. * @param __last2 An input iterator. * @return A pair of iterators pointing to the first mismatch. * * This compares the elements of two ranges using @c == and returns a pair * of iterators. The first iterator points into the first range, the * second iterator points into the second range, and the elements pointed * to by the iterators are not equal. */ template<typename _InputIterator1, typename _InputIterator2> inline pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) __glibcxx_function_requires(_EqualOpConcept< typename iterator_traits<_InputIterator1>::value_type, typename iterator_traits<_InputIterator2>::value_type>) __glibcxx_requires_valid_range(__first1, __last1); __glibcxx_requires_valid_range(__first2, __last2); return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, __gnu_cxx::__ops::__iter_equal_to_iter()); } /** * @brief Finds the places in ranges which don't match. * @ingroup non_mutating_algorithms * @param __first1 An input iterator. * @param __last1 An input iterator. * @param __first2 An input iterator. * @param __last2 An input iterator. * @param __binary_pred A binary predicate @link functors * functor@endlink. * @return A pair of iterators pointing to the first mismatch. * * This compares the elements of two ranges using the binary_pred * parameter, and returns a pair * of iterators. The first iterator points into the first range, the * second iterator points into the second range, and the elements pointed * to by the iterators are not equal. */ template<typename _InputIterator1, typename _InputIterator2, typename _BinaryPredicate> inline pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _BinaryPredicate __binary_pred) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) __glibcxx_requires_valid_range(__first1, __last1); __glibcxx_requires_valid_range(__first2, __last2); return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); } #endif _GLIBCXX_END_NAMESPACE_ALGO } // namespace std // NB: This file is included within many other C++ includes, as a way // of getting the base algorithms. So, make sure that parallel bits // come in too if requested. #ifdef _GLIBCXX_PARALLEL # include <parallel/algobase.h> #endif #endif
最新发布
12-20
#pragma region #include <iostream> #include <opencv4/opencv2/core/core.hpp> #include <opencv4/opencv2/highgui.hpp> #include <opencv4/opencv2/opencv.hpp> #include <opencv4/opencv2/imgproc/types_c.h> #include "pigpio.h" #include <thread> #include <cmath> #include <chrono> #include <time.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <assert.h> #include <termios.h> #include <string.h> #include <sys/time.h> #include <time.h> #include <sys/types.h> #include <errno.h> #include <signal.h> using namespace std; using namespace cv; #pragma endregion #define BAUD 9600//串口波特率 #pragma region int MAX_YU = 140; int MIN_YU = 60; // PID 各个数值 float kr = 0.00000001, kl = -0.0000001, lr = 0, ll = 0, br, bl; bool flag_avoid = false; // 躲避锥桶标志位 bool flag_zhang = false; // 未知 bool flag_voidcount = false; // 未知 bool flag_ren = false; // 人行道判断标志位 bool flag_yellow = false; double limit_voidtime = 0.17; bool flag_start; // 判断蓝色挡板标志位 bool flag_count; // 未知 double time_void = 100; // 未知 double angle; // 计算得到的角度 double angle_bi; // 避障角度 double angle_cover; //?????????? double speed_avoid = 10050; //??????? // double speed_delay = 10200;//????????????????? double heigth; double kuan; double low = 0, high = 0; Mat kernel_3 = Mat::ones(cv::Size(3, 3), CV_8U); Mat kernel = getStructuringElement(MORPH_RECT, Size(1, 1)); int shu = 0; int sum_avoid = 0; double width, x_r, x_l; //,heigth; //Mat frame, ca; static int ret; static int GPS; char r_buf[1024]; FILE* fp; double angle_x = 0; //???????y?? float a[3], w[3], Angle[3], h[3]; int flag_picture, duo_flag; // Rect list;cd ~ clock_t start_, end_, mid_time; static void on(int, void*); //double picture(); void GetROI(Mat src, Mat& ROI); double PID(double error1); vector<Point2f> get_lines_fangcheng(vector<Vec4i> lines); void Set_gpio(); Rect Obstacles(Mat img); Rect blue(Mat img); // 识别蓝色挡板 Rect yellow(Mat img); // 识别黄色挡板 string str = "sudo cp /home/pi/.Xauthority /root/"; int flag = system(str.c_str()); #pragma endregion //5G Mat img, img_HSV, img_HSV_mask, img_combined, img_per, img_clone, warped, frame; int start_flag = 1, find_blue_card_flag = 0, cross_flag = 0, music_flag = 0, avoid_flag = 0, car_blake_flag = 0; int LAB_Bmin = 190, LAB_Bmax = 255, HSL_Lmin = 157, HSL_Lmax = 255; int TIMECOUNT = 0; //定时器延时 int line_error = 0, line_error1 = 0, line_last_error = 0, line_last_error1 = 0; float center_x = 0, left_x = 0, right_x = 0; int line_y = 190; int rail_width_pix = 56;//跑道一半宽度 Point mousePos(0, 0); double kp = 0.28; // 0.155;//0.11?????;//0.16;//0.2;//0.3;//0.1???? 0.3???? double kd = 0.04; // 0.1;//0 ????? double kp1 = 0.25, kd1 = 0.02; double min_angle = 30; // 80 90 - 10 double max_angle = 30; // 100 int Angle_Z; enum class AvoidanceState { TRACKING, // 正常循迹状态 AVOIDING, // 避障中 RETURNING // 回归跑道中 }; AvoidanceState current_state = AvoidanceState::TRACKING; chrono::steady_clock::time_point avoidance_start_time; const int AVOIDANCE_DURATION = 1500; // 避障动作持续时间(毫秒) void cd(char* path) { chdir(path); } bool crossing(Mat image) { Mat roi, labels, stats, centroids, hui; GetROI(image, roi); //imshow("roi", roi); cvtColor(roi, hui, COLOR_BGR2GRAY); Mat binaryImage; threshold(hui, binaryImage, 180, 255, cv::THRESH_BINARY); imshow("binaryImage", binaryImage); int numComponents = cv::connectedComponentsWithStats(binaryImage, labels, stats, centroids); int crossingnum = 0; for (int i = 1; i < numComponents; i++) { int area = stats.at<int>(i, cv::CC_STAT_AREA); if (area > 200) { crossingnum++; } // cout<<area<<endl; } cout << "CrossingNum:" << crossingnum << endl; if (crossingnum >= 4) { cout << "find crossing" << endl; return true; } return false; } void gpio_init(void) { if (gpioInitialise() < 0) exit(1); gpioSetMode(13, PI_OUTPUT); gpioSetPWMrange(13, 40000); gpioSetPWMfrequency(13, 200); gpioPWM(13, 12000); gpioDelay(1000000); gpioSetMode(22, PI_OUTPUT); gpioSetPWMfrequency(22, 50); gpioSetPWMrange(22, 1000); gpioPWM(22, 75); // gpioSetMode(23, PI_OUTPUT); gpioSetPWMfrequency(23, 50); gpioSetPWMrange(23, 1000); gpioPWM(23, 70); //大上下小 gpioSetMode(12, PI_OUTPUT); // 设置GPIO12为PWM输出 gpioSetPWMfrequency(12, 50); // 50Hz标准频率 gpioSetPWMrange(12, 30000); // 设置PWM范围 printf("GPIO initial successful"); } void steering(int angle) { double value = (0.5 + (2.0 / 180.0) * angle) / 20 * 30000; // 100;//20000 gpioPWM(12, value); } void Start_motor(void) { cout << "1" << endl; gpioPWM(13, 10600); //gpioDelay(1000000); /*for (int x = 12000; x >= 9000; x -= 300) { cout << x << endl; gpioPWM(13, x); gpioDelay(500000); }*/ // 第二次启动时,可以注释掉 下面部分 //cout << "2" << endl; //gpioPWM(13, 12000); //gpioDelay(1000000); // 到此为止 //cout << "3" << endl; //gpioPWM(13, 11000); //gpioDelay(1000000); //cout << "4" << endl; //gpioPWM(13, 10300); //double value = speed_init; // ???动慢??? //gpioPWM(13, value); } void Control_stop(void) { gpioPWM(13, 12600); // 刹车 gpioDelay(50000); gpioPWM(13, 12200); // 保护 //gpioDelay(3000000); //gpioPWM(13, speed_mid); // 冲刺 } int uart_open(int fd, const char* pathname) { fd = open(pathname, O_RDWR | O_NOCTTY); if (-1 == fd) { perror("Can't Open Serial Port"); return(-1); } else printf("open %s success!\n", pathname); if (isatty(STDIN_FILENO) == 0) printf("standard input is not a terminal device\n"); else printf("isatty success!\n"); return fd; } int uart_set(int fd, int nSpeed, int nBits, char nEvent, int nStop) { struct termios newtio, oldtio; if (tcgetattr(fd, &oldtio) != 0) { perror("SetupSerial 1"); printf("tcgetattr( fd,&oldtio) -> %d\n", tcgetattr(fd, &oldtio)); return -1; } bzero(&newtio, sizeof(newtio)); newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; switch (nBits) { case 7: newtio.c_cflag |= CS7; break; case 8: newtio.c_cflag |= CS8; break; } switch (nEvent) { case 'o': case 'O': newtio.c_cflag |= PARENB; newtio.c_cflag |= PARODD; newtio.c_iflag |= (INPCK | ISTRIP); break; case 'e': case 'E': newtio.c_iflag |= (INPCK | ISTRIP); newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; break; case 'n': case 'N': newtio.c_cflag &= ~PARENB; break; default: break; } /*设置波特率*/ switch (nSpeed) { case 2400: cfsetispeed(&newtio, B2400); cfsetospeed(&newtio, B2400); break; case 4800: cfsetispeed(&newtio, B4800); cfsetospeed(&newtio, B4800); break; case 9600: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; case 115200: cfsetispeed(&newtio, B115200); cfsetospeed(&newtio, B115200); break; case 460800: cfsetispeed(&newtio, B460800); cfsetospeed(&newtio, B460800); break; default: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; } if (nStop == 1) newtio.c_cflag &= ~CSTOPB; else if (nStop == 2) newtio.c_cflag |= CSTOPB; newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 0; tcflush(fd, TCIFLUSH); if ((tcsetattr(fd, TCSANOW, &newtio)) != 0) { perror("com set error"); return -1; } printf("set done!\n"); return 0; } int uart_close(int fd) { assert(fd); close(fd); return 0; } int send_data(int fd, char* send_buffer, int length) { length = write(fd, send_buffer, length * sizeof(unsigned char)); return length; } int recv_data(int fd, char* recv_buffer, int length) { length = read(fd, recv_buffer, length); return length; } void Control_Xun(void) { int angle = kp * line_error + kd * (line_error - line_last_error); line_last_error = line_error; angle = 90 - angle; if (angle > 90 + max_angle) // 130 angle = 90 + max_angle; if (angle < 90 - min_angle) angle = 90 - min_angle; //cout <<"line_error"<<line_error<<"angle:" << angle << endl; //cout << "循迹处理完毕" << endl; steering(angle); } //void Control_avoid(void) { // const int DEAD_ZONE = 30; // 中心死区阈值(像素) // const int AVOID_ANGLE_OFFSET = 25; // 避让角度偏移量 // // // 1. 计算基础转向角度(PD控制) // // 注意:根据转向特性调整符号(angle越大越左转) // int angle = 90 + (kp1 * line_error1 + kd1 * (line_error1 - line_last_error1)); // line_last_error1 = line_error1; // // 2. 中心区域强制避让(关键修正) // if (abs(line_error1) < DEAD_ZONE) { // // 修正避让方向判断逻辑 // // 锥桶在右侧(line_error1 > 0):需要向左避让(增大角度) // // 锥桶在左侧(line_error1 < 0):需要向右避让(减小角度) // if (line_error1 > 0) { // angle = 90 + AVOID_ANGLE_OFFSET; // 向左避让 // } // else { // angle = 90 - AVOID_ANGLE_OFFSET; // 向右避让 // } // } // // // 3. 角度限幅保护(根据转向特性调整) // // 角度限幅在60-120度范围(90°为直行) // if (angle > 98) angle = 98; // 最大左转限制 // if (angle < 82) angle = 82; // 最大右转限制 // // cout << "avoid_angle:" << angle << endl; // steering(angle); //} // 修改Control_avoid函数,添加跑道保持逻辑 void Control_avoid(void) { const int DEAD_ZONE = 30; // 中心死区阈值(像素) const int AVOID_ANGLE_OFFSET = 25; // 避让角度偏移量 // 1. 获取当前跑道中心线偏差(来自循迹模块) int track_error = line_error; // 循迹偏差 // 2. 状态机控制 int base_angle = 90; switch (current_state) { case AvoidanceState::TRACKING: // 正常循迹控制 base_angle = 90 + (kp1 * track_error + kd1 * (track_error - line_last_error)); line_last_error = track_error; break; case AvoidanceState::AVOIDING: { // 避障控制逻辑 base_angle = 90 + (kp1 * line_error1 + kd1 * (line_error1 - line_last_error1)); line_last_error1 = line_error1; // 中心区域强制避让 if (abs(line_error1) < DEAD_ZONE) { if (line_error1 > 0) { base_angle = 90 + AVOID_ANGLE_OFFSET; } else { base_angle = 90 - AVOID_ANGLE_OFFSET; } } // 检查避障时间是否结束 auto now = chrono::steady_clock::now(); auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - avoidance_start_time).count(); if (elapsed > AVOIDANCE_DURATION) { current_state = AvoidanceState::RETURNING; avoidance_start_time = now; // 重置计时器 } break; } case AvoidanceState::RETURNING: { // 回归跑道逻辑 int return_direction = (line_error1 > 0) ? -1 : 1; // 与避让方向相反 base_angle = 90 + return_direction * AVOID_ANGLE_OFFSET; // 添加循迹误差补偿 base_angle += track_error * 0.3; // 检查是否应该返回循迹状态 auto now = chrono::steady_clock::now(); auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - avoidance_start_time).count(); // 条件1:回归时间结束(1秒) // 条件2:检测到两条跑道线(正常循迹状态) if (elapsed > 1000 || (abs(track_error) < 20)) { current_state = AvoidanceState::TRACKING; } break; } } // 3. 平滑过渡处理(防止角度突变) static int last_angle = 90; const int MAX_CHANGE = 8; // 最大角度变化率 if (abs(base_angle - last_angle) > MAX_CHANGE) { base_angle = last_angle + ((base_angle > last_angle) ? MAX_CHANGE : -MAX_CHANGE); } last_angle = base_angle; // 4. 角度限幅保护 if (base_angle > 110) base_angle = 110; // 最大左转限制 if (base_angle < 70) base_angle = 70; // 最大右转限制 // 5. 执行转向 steering(base_angle); // 调试信息 string state_str; switch (current_state) { case AvoidanceState::TRACKING: state_str = "TRACKING"; break; case AvoidanceState::AVOIDING: state_str = "AVOIDING"; break; case AvoidanceState::RETURNING: state_str = "RETURNING"; break; } cout << "State: " << state_str << " | Angle: " << base_angle << endl; } void GetROI(Mat src, Mat& ROI) { // 取得源图像的长宽 int width = src.cols; int height = src.rows; Rect rect(Point(0, (height / 20) * 10), Point(width, (height / 20) * 17)); // 按比例截取 ROI = src(rect); // 赋值ROI } vector<Point2f> get_lines_fangcheng(vector<Vec4i> lines) { // 遍历概率霍夫变换检测到的直线 float k = 0; // 斜率 float b = 0; // 截距 vector<Point2f> lines_fangcheng; for (unsigned int i = 0; i < lines.size(); i++) { k = (double)(lines[i][3] - lines[i][1]) / (double)(lines[i][2] - lines[i][0]); b = (double)lines[i][1] - k * (double)lines[i][0]; lines_fangcheng.push_back(Point2f(k, b)); } return lines_fangcheng; } //Rect blue(Mat img) //{ // Mat HSV, roi; // GetROI(img, roi); // cvtColor(roi, HSV, COLOR_BGR2HSV); // Scalar Lower(100, 100, 50); // Scalar Upper(120, 255, 255); // Mat mask; // inRange(HSV, Lower, Upper, mask); // Mat erosion_dilation; // erode(mask, erosion_dilation, kernel_3, Point(-1, -1), 1, BORDER_CONSTANT, morphologyDefaultBorderValue()); // dilate(erosion_dilation, erosion_dilation, kernel_3, Point(-1, -1), 1, BORDER_CONSTANT, morphologyDefaultBorderValue()); // Mat target; // bitwise_and(roi, roi, target, erosion_dilation); // Mat binary; // threshold(erosion_dilation, binary, 127, 255, THRESH_BINARY); // imshow("blue", binary); // vector<vector<Point>> contours; // findContours(binary, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); // int maxContourIndex = -1; // double maxContourArea = 0.0; // for (int i = 0; i < contours.size(); i++) // { // double area = cv::contourArea(contours[i]); // if (area > maxContourArea) // { // maxContourArea = area; // maxContourIndex = i; // } // } // if (maxContourIndex != -1) { // Rect boundRect = boundingRect(contours[maxContourIndex]); // return boundRect; // } // else { // return Rect(); // } //} //Rect Obstacles(Mat img)//识别到锥桶 //{ // Rect obstacle_object = blue(img);//识别到的蓝色物体 // if (obstacle_object.height > 5 && obstacle_object.height < 100)//对识别到的蓝色物体限幅, // { // rectangle(img, Point(obstacle_object.x, obstacle_object.y + frame.rows / 2), Point(obstacle_object.x + obstacle_object.width, obstacle_object.y + obstacle_object.height + frame.rows / 2), Scalar(0, 255, 0), 3); // return obstacle_object; // } // return Rect(); //} Rect blue(Mat img) { // 定义有效区域面积阈值 const int MIN_AREA = 0; // 最小面积阈值(像素) const int MAX_AREA = 5000; // 最大面积阈值(像素) Mat HSV, roi; GetROI(img, roi); cvtColor(roi, HSV, COLOR_BGR2HSV); // 改进:使用自适应HSV范围 Scalar Lower(100, 100, 50); Scalar Upper(120, 255, 255); // 改进:计算图像亮度并动态调整阈值 Scalar mean_val = mean(HSV); if (mean_val[2] > 150) { // 高亮度环境 Lower.val[1] = 120; // 增加饱度下限 } else if (mean_val[2] < 50) { // 低亮度环境 Upper.val[2] = 200; // 降低明度上限 } Mat mask; inRange(HSV, Lower, Upper, mask); // 改进:增强形态学处理 Mat erosion_dilation; Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5)); erode(mask, erosion_dilation, kernel, Point(-1, -1), 2); dilate(erosion_dilation, erosion_dilation, kernel, Point(-1, -1), 2); // 改进:添加开运算去除小噪点 morphologyEx(erosion_dilation, erosion_dilation, MORPH_OPEN, kernel); Mat target; bitwise_and(roi, roi, target, erosion_dilation); Mat binary; threshold(erosion_dilation, binary, 127, 255, THRESH_BINARY); imshow("blue", binary); vector<vector<Point>> contours; findContours(binary, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); int maxContourIndex = -1; double maxContourArea = 0.0; // 改进:添加宽高比约束 const float MIN_ASPECT_RATIO = 0.5; // 最小宽高比 const float MAX_ASPECT_RATIO = 2.0; // 最大宽高比 for (int i = 0; i < contours.size(); i++) { double area = cv::contourArea(contours[i]); // 跳过不满足面积条件的轮廓 if (area < MIN_AREA || area > MAX_AREA) continue; // 计算轮廓的边界矩形 Rect boundRect = boundingRect(contours[i]); float aspect_ratio = static_cast<float>(boundRect.width) / boundRect.height; // 跳过不满足宽高比的轮廓 if (aspect_ratio < MIN_ASPECT_RATIO || aspect_ratio > MAX_ASPECT_RATIO) continue; // 更新最大有效轮廓 if (area > maxContourArea) { maxContourArea = area; maxContourIndex = i; } } if (maxContourIndex != -1) { Rect boundRect = boundingRect(contours[maxContourIndex]); // 最终有效性检查(面积+宽高比) float aspect_ratio = static_cast<float>(boundRect.width) / boundRect.height; if (boundRect.area() >= MIN_AREA && boundRect.area() <= MAX_AREA && aspect_ratio >= MIN_ASPECT_RATIO && aspect_ratio <= MAX_ASPECT_RATIO) { return boundRect; } } return Rect(); // 返回空矩形表示未找到有效区域 } Rect Obstacles(Mat img) { Rect obstacle_object = blue(img); // 检测到有效锥桶 if (obstacle_object.height > 5 && obstacle_object.height < 100) { // 计算在原图中的坐标位置 int roi_offset_y = img.rows / 2; // ROI起始y坐标 Point topLeft(obstacle_object.x, obstacle_object.y + roi_offset_y); Point bottomRight(obstacle_object.x + obstacle_object.width, obstacle_object.y + obstacle_object.height + roi_offset_y); // 在原图上绘制绿色框 rectangle(img, topLeft, bottomRight, Scalar(0, 255, 0), 3); // 更新状态为避障中 if (current_state == AvoidanceState::TRACKING) { current_state = AvoidanceState::AVOIDING; avoidance_start_time = chrono::steady_clock::now(); } return obstacle_object; } return Rect(); } int car_start(Mat img) { Rect start_flag = blue(img); // cout << start_flag.width << " " << start_flag.height << endl; if (start_flag.width > 50 && start_flag.height > 50) { return 0; // ?????????? } return 1; // ????????I???? } void camera(int angl_x, int angl_y) { gpioPWM(22, angl_x);//大左小右 gpioPWM(23, angl_y); //大上下小 } void GPS_init(void) { char r_buf[1024]; bzero(r_buf, 1024); GPS = uart_open(GPS, "/dev/ttyUSB0");/*串口号/dev/ttySn,USB口号/dev/ttyUSBn */ if (GPS == -1) { fprintf(stderr, "GPS error\n"); exit(EXIT_FAILURE); } if (uart_set(GPS, BAUD, 8, 'N', 1) == -1) { fprintf(stderr, "GPS set failed!\n"); exit(EXIT_FAILURE); } } void ParseData(char chr) { static char chrBuf[100]; static unsigned char chrCnt = 0; signed short sData[4]; unsigned char i; time_t now; chrBuf[chrCnt++] = chr; if (chrCnt < 11) return; if ((chrBuf[0] != 0x55) || ((chrBuf[1] & 0x50) != 0x50)) { printf("Error:%x %x\r\n", chrBuf[0], chrBuf[1]); memcpy(&chrBuf[0], &chrBuf[1], 10); chrCnt--; return; } memcpy(&sData[0], &chrBuf[2], 8); switch (chrBuf[1]) { case 0x51: for (i = 0; i < 3; i++) a[i] = (float)sData[i] / 32768.0 * 16.0; time(&now); //printf("\r\nT:%s a:%6.3f %6.3f %6.3f ", asctime(localtime(&now)), a[0], a[1], a[2]); break; case 0x52: for (i = 0; i < 3; i++) w[i] = (float)sData[i] / 32768.0 * 2000.0; //printf("w:%7.3f %7.3f %7.3f ", w[0], w[1], w[2]); break; case 0x53: for (i = 0; i < 3; i++) Angle[i] = (float)sData[i] / 32768.0 * 180.0; //printf("A:%7.3f %7.3f %7.3f ", Angle[0], Angle[1], Angle[2]); Angle_Z = Angle[2] - 167; printf("Z:%d \r\n", Angle_Z); break; case 0x54: for (i = 0; i < 3; i++) h[i] = (float)sData[i]; //printf("h:%4.0f %4.0f %4.0f ", h[0], h[1], h[2]); break; } chrCnt = 0; } void Get_GPS_data(void) { while (1) { ret = recv_data(GPS, r_buf, 44); if (ret == -1) { fprintf(stderr, "uart read failed!\n"); exit(EXIT_FAILURE); } for (int i = 0; i < ret; i++) ParseData(r_buf[i]); usleep(1000); } //usleep(1000); } void audio(void) { system("omxplayer /home/pi/car435/car.wav"); } Mat HLS_Lthresh(const cv::Mat& img, int min_thresh = 220, int max_thresh = 255) { Mat hls; cvtColor(img, hls, COLOR_BGR2HLS); vector<Mat> channels; split(hls, channels); Mat l_channel = channels[1]; double minVal, maxVal; minMaxLoc(l_channel, &minVal, &maxVal); l_channel.convertTo(l_channel, CV_8UC1, 255.0 / maxVal); Mat binary_output = Mat::zeros(l_channel.size(), CV_8UC1); inRange(l_channel, min_thresh, max_thresh, binary_output); return binary_output; } Mat LAB_BThreshold(const Mat& img, int min_thresh = 190, int max_thresh = 255) { Mat lab; cvtColor(img, lab, COLOR_BGR2Lab); vector<Mat> lab_channels; split(lab, lab_channels); Mat b_channel = lab_channels[2]; //cout<<b_channel<<endl; double maxVal; minMaxLoc(b_channel, nullptr, &maxVal); //cout<<maxVal<<endl; if (maxVal > 175) { b_channel.convertTo(b_channel, CV_8UC1, 255.0 / maxVal); } Mat binary_output = Mat::zeros(b_channel.size(), CV_8UC1); inRange(b_channel, min_thresh, max_thresh, binary_output); return binary_output; } Mat combineThresholds(const Mat& img_LThresh, const Mat& img_BThresh) { Mat combined = Mat::zeros(img_BThresh.size(), CV_8UC1); bitwise_or(img_LThresh, img_BThresh, combined); return combined; } struct LaneData { vector<Point> left_points; vector<Point> right_points; vector<float> left_fit; vector<float> right_fit; vector<float> mid_fit; vector<Rect> left_windows; vector<Rect> right_windows; }; Mat getHistogram(const Mat& binary_img) { Mat hist; reduce(binary_img.rowRange(binary_img.rows / 2, binary_img.rows), hist, 0, REDUCE_SUM, CV_32S); return hist; } pair<int, int> findLaneBases(const Mat& hist) { int midpoint = hist.cols / 2; int quarter = midpoint / 2; Point left_base, right_base; minMaxLoc(hist.colRange(quarter, midpoint), 0, 0, 0, &left_base); minMaxLoc(hist.colRange(midpoint, midpoint + quarter), 0, 0, 0, &right_base); return { left_base.x + quarter, right_base.x + midpoint }; } LaneData slidingWindow(const Mat& binary_img, int nwindows = 9, int margin = 20, int minpix = 10) { LaneData result; auto [leftx, rightx] = findLaneBases(getHistogram(binary_img)); //cout<<"leftx:"<<leftx<<"rightx:"<<rightx<<endl; int window_height = binary_img.rows / nwindows; vector<Point> nonzero; findNonZero(binary_img, nonzero); for (int i = 0; i < nwindows; ++i) { int win_y_low = binary_img.rows - (i + 1) * window_height; int win_y_high = binary_img.rows - i * window_height; Rect left_win(leftx - margin, win_y_low, 2 * margin, window_height); Rect right_win(rightx - margin, win_y_low, 2 * margin, window_height); result.left_windows.push_back(left_win); result.right_windows.push_back(right_win); for (const auto& pt : nonzero) { if (left_win.contains(pt)) result.left_points.push_back(pt); if (right_win.contains(pt)) result.right_points.push_back(pt); } if (result.left_points.size() > minpix) leftx = mean(result.left_points)[0]; if (result.right_points.size() > minpix) rightx = mean(result.right_points)[0]; } return result; } vector<float> polyFit(const vector<Point>& points, int order = 2) { if (points.size() < order + 1) { cout << "data no enough for" << order << "profit" << endl; return {}; } Mat A(points.size(), order + 1, CV_32F); Mat B(points.size(), 1, CV_32F); for (size_t i = 0; i < points.size(); ++i) { float y = points[i].y; A.at<float>(i, 0) = y * y; A.at<float>(i, 1) = y; A.at<float>(i, 2) = 1.0f; B.at<float>(i, 0) = points[i].x; } Mat coeff; solve(A, B, coeff, DECOMP_SVD); //solve(A, B, coeff, DECOMP_QR); return { coeff.at<float>(0), coeff.at<float>(1), coeff.at<float>(2) }; } vector<float> calculateCenterLaneCoefficient(const vector<float>& left_fit, const vector<float>& right_fit) { if (left_fit.size() != 3 || right_fit.size() != 3) { cout << "Invalid polynomial coefficients" << endl; return {}; } vector<float> center_fit(3); center_fit[0] = (left_fit[0] + right_fit[0]) / 2.0f; // A 系数 center_fit[1] = (left_fit[1] + right_fit[1]) / 2.0f; // B 系数 center_fit[2] = (left_fit[2] + right_fit[2]) / 2.0f; // C 系数 //cout<<center_fit[0]<<center_fit[1]<<center_fit[2]<<endl; return center_fit; } float calculateXFromPolynomial(const vector<float>& fit, float y) { if (fit.size() != 3) return 0.0f; return fit[0] * y * y + fit[1] * y + fit[2]; } void visualize(Mat& img, const LaneData& data) { // 绘制滑动窗口 // for (const auto& win : data.left_windows) // rectangle(img, win, Scalar(0,255,0), 2); // for (const auto& win : data.right_windows) // rectangle(img, win, Scalar(0,255,0), 2); // 绘制车道线点 for (const auto& pt : data.left_points) circle(img, pt, 3, Scalar(255, 0, 0), -1); for (const auto& pt : data.right_points) circle(img, pt, 3, Scalar(0, 0, 255), -1); // 绘制拟合曲线 if (!data.left_fit.empty()) { for (int y = 0; y < img.rows; ++y) { int x = data.left_fit[0] * y * y + data.left_fit[1] * y + data.left_fit[2]; if (x >= 0 && x < img.cols) circle(img, Point(x, y), 2, Scalar(0, 0, 255), -1); } } if (!data.right_fit.empty()) { for (int y = 0; y < img.rows; ++y) { int x = data.right_fit[0] * y * y + data.right_fit[1] * y + data.right_fit[2]; if (x >= 0 && x < img.cols) circle(img, Point(x, y), 2, Scalar(0, 0, 255), -1); } } circle(img, Point(center_x, line_y), 3, Scalar(0, 255, 0), -1); } bool Contour_Area(vector<Point> contour1, vector<Point> contour2) { return contourArea(contour1) > contourArea(contour2); } Mat customEqualizeHist(const Mat& inputImage, float alpha) { Mat enhancedImage; equalizeHist(inputImage, enhancedImage); return alpha * enhancedImage + (1 - alpha) * inputImage; } void timer(void)//定时器中断 { TIMECOUNT++; std::cout << "timer:" << TIMECOUNT << std::endl; } void reset_timer(void)//定时器中断 { TIMECOUNT = 0; } //int PID(int error) //{ // const float Kp = 0.8f; // int output = static_cast<int>(Kp * error); // // output = max(-30, min(30, output)); // return output; //} int timer_interrupt(void)//定时器 { while (true) { //timer(); this_thread::sleep_for(chrono::milliseconds(50)); Control_Xun(); } return 0; } void onTrackbar(int, void*) { LAB_Bmin = getTrackbarPos("LAB_Bmin", "TrackBars"); LAB_Bmax = getTrackbarPos("LAB_Bmax", "TrackBars"); HSL_Lmin = getTrackbarPos("HSL_Lmin", "TrackBars"); HSL_Lmax = getTrackbarPos("HSL_Lmax", "TrackBars"); } void UI_init(void) { namedWindow("TrackBars", WINDOW_NORMAL); resizeWindow("TrackBars", 320, 240); moveWindow("TrackBars", 0, 50); // 设置窗口位置 createTrackbar("LAB_Bmin", "TrackBars", &LAB_Bmin, 255, onTrackbar); setTrackbarPos("LAB_Bmin", "TrackBars", LAB_Bmin); createTrackbar("LAB_Bmax", "TrackBars", &LAB_Bmax, 255, onTrackbar); setTrackbarPos("LAB_Bmax", "TrackBars", LAB_Bmax); createTrackbar("HSL_Lmin", "TrackBars", &HSL_Lmin, 255, onTrackbar); setTrackbarPos("HSL_Lmin", "TrackBars", HSL_Lmin); createTrackbar("HSL_Lmax", "TrackBars", &HSL_Lmax, 255, onTrackbar); setTrackbarPos("HSL_Lmax", "TrackBars", HSL_Lmax); } void onMouse(int event, int x, int y, int flags, void* userdata) { mousePos = Point(x, y); } void test(void) { while (1) { line_error = -100; this_thread::sleep_for(chrono::milliseconds(500)); line_error = 100; this_thread::sleep_for(chrono::milliseconds(500)); } } void find_blue_card(void)//检测到蓝色挡板 { vector<vector<Point>> contours; vector<Vec4i> hierarcy; findContours(img_HSV_mask, contours, hierarcy, RETR_EXTERNAL, CHAIN_APPROX_NONE); if (contours.size() > 0) { sort(contours.begin(), contours.end(), Contour_Area); //cout<<cStart_motorontours.size()<<endl; vector<vector<Point>> newContours; for (const vector<Point>& contour : contours) { Point2f center; float radius; minEnclosingCircle(contour, center, radius); if (center.y > 90 && center.y < 160) { newContours.push_back(contour); } } contours = newContours; if (contours.size() > 0) { if (contourArea(contours[0]) > 500) { cout << "find blue card" << endl; Point2f center; float radius; minEnclosingCircle(contours[0], center, radius); circle(img, center, static_cast<int>(radius), Scalar(0, 255, 0), 2); find_blue_card_flag = 1; } else { cout << "not blue card" << endl; } } } else { cout << "not blue card" << endl; } } void find_blue_card_remove(void)//蓝色挡板移开 { cout << "detecting blue card remove" << endl; vector<vector<Point>> contours; vector<Vec4i> hierarcy; findContours(img_HSV_mask, contours, hierarcy, RETR_EXTERNAL, CHAIN_APPROX_NONE); if (contours.size() > 0) { sort(contours.begin(), contours.end(), Contour_Area); vector<vector<Point>> newContours; for (const vector<Point>& contour : contours) { Point2f center; float radius; minEnclosingCircle(contour, center, radius); if (center.y > 90 && center.y < 160) { newContours.push_back(contour); } } contours = newContours; if (contours.size() == 0) { start_flag = 0; cout << "blue card remove" << endl; //Start_motor(); //sleep(2); } } else { start_flag = 0; cout << "blue card remove" << endl; //Start_motor(); //sleep(2); } } int crossroad(void)//斑马线识别 { VideoCapture capture; capture.open(2); if (!capture.isOpened()) { cout << "Can not open camera" << endl; return -1; } else cout << "camera open successful" << endl; capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G')); capture.set(cv::CAP_PROP_FPS, 30); capture.set(cv::CAP_PROP_FRAME_WIDTH, 320); capture.set(cv::CAP_PROP_FRAME_HEIGHT, 240); this_thread::sleep_for(chrono::milliseconds(2000)); //让图像稳定 cout << "Program started" << endl; Mat img_cross; Mat blur; while (1) { capture >> img_cross; GaussianBlur(img_cross, blur, Size(5, 5), 0); Mat hsv; cvtColor(blur, hsv, COLOR_BGR2HSV); Scalar lower_white = Scalar(0, 0, 200); Scalar upper_white = Scalar(180, 40, 255); Mat cross_mask; inRange(hsv, lower_white, upper_white, cross_mask); // Mat edges; // Canny(blur, edges, 50, 150); // bitwise_or(cross_mask, edges, cross_mask); Mat kernel = getStructuringElement(MORPH_RECT, Size(7, 7)); //dilate(mask1, mask1, kernel); //erode(mask1, mask1, kernel); morphologyEx(cross_mask, cross_mask, MORPH_CLOSE, kernel); //Rect roi(0,120,320,120);//shang Rect roi(0, 260, 640, 220);//xia Mat region = cross_mask(roi); //imshow("combined_image", region); //imshow("Full Mask", cross_mask); // 完整图像 //imshow("ROI Region", region); // 仅用于调试检测区 //imshow("combined_image", mask1_roi); int stripe_count = 0, transitions = 0; for (int i = 0; i < region.rows; i++) { transitions = 0; for (int j = 5; j < region.cols - 5; j++) { if (region.at<uchar>(i, j) != region.at<uchar>(i, j - 1)) transitions++; } //cout<<"transitions:"<<transitions<<endl; if (transitions >= 6) stripe_count++; } cross_flag = (stripe_count >= 16) ? 1 : 0; cout << "stripe_count" << stripe_count << "cross_flag:" << cross_flag << endl; if (cv::waitKey(1) == 27)break; } gpioTerminate(); capture.release(); // 释放摄像头 destroyAllWindows(); // 关闭所有窗口 //uart_close(GPS); return 0; } Mat per_wt(Mat& frame) { int img_h, img_w; img_clone = frame.clone(); img_h = img_clone.rows; // 图像高度 img_w = img_clone.cols; vector<cv::Point2f> src = { Point2f(125, 198), Point2f(213, 198), Point2f(295, 237), Point2f(55, 237) }; vector<cv::Point2f> dst = { Point2f(100,0), Point2f(img_w - 100, 0), Point2f(img_w - 100, img_h), Point2f(100, img_h) }; // 定义目标坐标(变换后的四个点) vector<cv::Point> polygon; for (const auto& pt : src) { polygon.push_back(Point(static_cast<int>(pt.x), static_cast<int>(pt.y))); } polylines(img_clone, polygon, 1, Scalar(0, 0, 255), 3, cv::LINE_AA); // 计算透视变换矩阵 Mat M = getPerspectiveTransform(src, dst); Mat Minv = getPerspectiveTransform(dst, src); // 应用透视 warpPerspective(frame, warped, M, cv::Size(img_w, img_h), cv::INTER_LINEAR); waitKey(5); return warped; } int find_line(void) //循迹线程 { // 初始化程序 //UI_init(); VideoCapture capture; capture.open(0); if (!capture.isOpened()) { cout << "Can not open camera" << endl; return -1; } else cout << "camera open successful" << endl; capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G')); capture.set(cv::CAP_PROP_FPS, 30); capture.set(cv::CAP_PROP_FRAME_WIDTH, 320); capture.set(cv::CAP_PROP_FRAME_HEIGHT, 240); this_thread::sleep_for(chrono::milliseconds(1000)); //让图像稳定 cout << "Program started" << endl; while (1) { capture >> img; if (start_flag == 1) { cvtColor(img, img_HSV, COLOR_BGR2HSV); Scalar HSV_L = Scalar(100, 43, 46); Scalar HSV_H = Scalar(124, 255, 255); inRange(img_HSV, HSV_L, HSV_H, img_HSV_mask); Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5)); morphologyEx(img_HSV_mask, img_HSV_mask, MORPH_OPEN, kernel); morphologyEx(img_HSV_mask, img_HSV_mask, MORPH_CLOSE, kernel); if (find_blue_card_flag == 0)find_blue_card(); else find_blue_card_remove(); } else { img_per = per_wt(img); Mat HLS_Lresult = HLS_Lthresh(img_per, HSL_Lmin, HSL_Lmax); Mat LAB_Bresult = LAB_BThreshold(img_per, LAB_Bmin, LAB_Bmax); img_combined = combineThresholds(HLS_Lresult, LAB_Bresult); Mat white_image(img.size(), img.type(), Scalar::all(255)); LaneData lanes = slidingWindow(img_combined); lanes.left_fit = polyFit(lanes.left_points); lanes.right_fit = polyFit(lanes.right_points); if (lanes.left_fit.size() != 3 || lanes.right_fit.size() != 3) { if (lanes.left_fit.size() != 3)center_x = lanes.right_fit[0] * line_y * line_y + lanes.right_fit[1] * line_y + lanes.right_fit[2] - rail_width_pix; if (lanes.right_fit.size() != 3)center_x = lanes.left_fit[0] * line_y * line_y + lanes.left_fit[1] * line_y + lanes.left_fit[2] + rail_width_pix; cout << center_x << endl; } if (lanes.left_fit.size() == 3 && lanes.right_fit.size() == 3) { center_x = (lanes.right_fit[0] * line_y * line_y + lanes.right_fit[1] * line_y + lanes.right_fit[2] + lanes.left_fit[0] * line_y * line_y + lanes.left_fit[1] * line_y + lanes.left_fit[2]) / 2; cout << center_x << endl; } line_error = center_x - 160; //cout << left_x << "," << right_x << "," << center_x << "," << line_error << endl; visualize(white_image, lanes); //namedWindow("img", cv::WINDOW_NORMAL); // 创建可调整大小的窗口 //resizeWindow("img", 320, 240); // 设置窗口尺寸 //moveWindow("img", 320, 50); // 设置窗口位置 //imshow("img", img_clone); //namedWindow("combined_image", cv::WINDOW_NORMAL); // 创建可调整大小的窗口 //resizeWindow("combined_image", 320, 240); // 设置窗口尺寸 //moveWindow("combined_image", 640, 50); // 设置窗口位置 //imshow("combined_image", img_combined); //namedWindow("white_image", cv::WINDOW_NORMAL); // 创建可调整大小的窗口 //resizeWindow("white_image", 320, 240); // 设置窗口尺寸 //moveWindow("white_image", 960, 50); // 设置窗口位置 //imshow("white_image", white_image); if (cross_flag == 1) { Control_stop(); audio(); break; } } if (cv::waitKey(1) == 27)break; //if(car_blake_flag == 1) ;//break;//结束代码 } gpioTerminate(); capture.release(); // 释放摄像头 destroyAllWindows(); // 关闭所有窗口 //uart_close(GPS); return 0; } //————————————————————————— int Blue_cone(void) { VideoCapture capture; capture.open(2); if (!capture.isOpened()) { cout << "Error: Camera not available" << endl; return -1; } else cout << "camera open successful" << endl; capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G')); capture.set(cv::CAP_PROP_FPS, 30); capture.set(cv::CAP_PROP_FRAME_WIDTH, 640); capture.set(cv::CAP_PROP_FRAME_HEIGHT, 480); this_thread::sleep_for(chrono::milliseconds(1000)); //让图像稳定 cout << "Program started" << endl; current_state = AvoidanceState::TRACKING; while (1) { capture >> frame; if (!capture.read(frame)) { cout << "Frame read error!" << endl; break; } Rect cone = Obstacles(frame); imshow("blue_cone", frame); // 无论是否检测到锥桶都执行控制 Control_avoid(); if (waitKey(1) == 27) break; } gpioTerminate(); capture.release(); // 释放摄像头 destroyAllWindows(); // 关闭所有窗口 return 0; } //————————————————————————-- int main() { gpioTerminate(); gpio_init(); GPS_init(); camera(72, 86); steering(90); thread thread1(find_line);//循迹线程 thread thread2(Get_GPS_data);//test thread thread3(timer_interrupt);//定时器功能 thread thread4(crossroad); thread thread5(Blue_cone);//避障线程 thread1.join(); thread2.join(); thread3.join(); thread4.join(); thread5.join(); return 0;//GPS_init(); } //取数据调试的main函数 //int main(void) //{ // UI_init(); // gpioTerminate(); // gpio_init(); // camera(72,86); // steering(90); // // Mat img = imread("C:/Users/wtcat/CLionProjects/untitled7/test_images/225.jpg",IMREAD_COLOR_BGR); // // if(img.empty()) // // { // // std::cerr << "Error: Could not load the image" << std::endl; // // return -1; // // } // VideoCapture capture; // capture.open(2); // if (!capture.isOpened()) // { // cout << "Can not open camera!" << std::endl; // return -1; // } // capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G')); // capture.set(cv::CAP_PROP_FPS, 30); // capture.set(cv::CAP_PROP_FRAME_WIDTH, 320); // capture.set(cv::CAP_PROP_FRAME_HEIGHT, 240); // this_thread::sleep_for(chrono::milliseconds(1000)); //让图像稳定 // Mat img_per,img_combined; // string windowName = "XY"; // namedWindow(windowName, WINDOW_AUTOSIZE); // setMouseCallback(windowName, onMouse, NULL); // while (1) // { // capture>>img; // img_per=per_wt(img); // string coordText = "X=" + to_string(mousePos.x) + " Y=" + to_string(mousePos.y); // putText(img_clone, coordText, Point(15, 35),FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 255, 100), 2); // moveWindow(windowName, 320, 50); // imshow(windowName, img_clone); // Mat HLS_Lresult = HLS_Lthresh(img_per,HSL_Lmin,HSL_Lmax); // Mat LAB_Bresult = LAB_BThreshold(img_per,LAB_Bmin,LAB_Bmax); // img_combined=combineThresholds(HLS_Lresult, LAB_Bresult); // //img_combined=HLS_Lresult; // Mat white_image(img.size(), img.type(), Scalar::all(255)); // LaneData lanes = slidingWindow(img_combined); // lanes.left_fit = polyFit(lanes.left_points); // lanes.right_fit = polyFit(lanes.right_points); // visualize(white_image, lanes); // namedWindow("combined_image", cv::WINDOW_NORMAL); // 创建可调整大小的窗口 // resizeWindow("combined_image", 320, 240); // 设置窗口尺寸 // moveWindow("combined_image", 640, 50); // 设置窗口位置 // imshow("combined_image", img_combined); // namedWindow("white_image", cv::WINDOW_NORMAL); // 创建可调整大小的窗口 // resizeWindow("white_image", 320, 240); // 设置窗口尺寸 // moveWindow("white_image", 960,50); // 设置窗口位置 // imshow("white_image", white_image); // if (cv::waitKey(1) == 27) // { // break; // } // //if(car_blake_flag == 1) ;//break;//结束代码 // } // capture.release(); // 释放摄像头 // destroyAllWindows(); // 关闭所有窗口 // return 0; //}现在,在跑道尽头有一块停车区域(将跑道一分为二分左右两侧,并分别贴着AB标识),在停车区域前贴有一块标识(A或B),小车要识别到A或者B,并跑进相应的停车区域停车,停车区域有一条黄线横在跑道上,AB标识均为蓝底白字,黄线指示牌均贴在地上,是先识别到一个指示牌A或B然后根据他再往前走识别到黄线及黄线后方两块区域AB停进相应的区域。请帮我补程序
11-18
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值