fork download
  1.  
  2. namespace cv
  3. {
  4.  
  5. using Scalar = double;
  6.  
  7. struct Mat
  8. {};
  9.  
  10. struct Point2i
  11. {};
  12.  
  13. inline void swap(Mat& a, Mat& b)
  14. {}
  15.  
  16. }
  17.  
  18. // basic_types.hpp
  19.  
  20. #include <cstdint>
  21.  
  22. namespace cvip
  23. {
  24.  
  25. // Aliases for most used types from std
  26. //
  27.  
  28. using uint_t = std::uint32_t;
  29. using upix_t = std::uint8_t;
  30. using wpix_t = std::uint16_t;
  31.  
  32.  
  33. // Aliases for most common types in cv
  34.  
  35. using vscalar = double;
  36. using mscalar = cv::Scalar;
  37.  
  38. using matrix = cv::Mat;
  39.  
  40. using point = cv::Point2i;
  41.  
  42.  
  43. // Algoritms/Scanning execution model
  44. //
  45.  
  46. enum class execution_model : int
  47. {
  48. parallel, sequential
  49. };
  50.  
  51. }
  52.  
  53.  
  54. // i_operator.hpp
  55.  
  56. #include <memory>
  57. #include <type_traits>
  58.  
  59. namespace cvip
  60. {
  61.  
  62. namespace core
  63. {
  64.  
  65. // Interface for image operator classes
  66. //
  67.  
  68. class i_operator
  69. {
  70. protected:
  71.  
  72. // operator chain node type
  73. //
  74. using opnode_t = std::shared_ptr<i_operator>;
  75.  
  76. // apply operator on matrix
  77. //
  78. // rhs : A modifiable reference to a smart-reference image container.
  79. // On input, it holds a reference to the original (right hand
  80. // side) operand. On output, it holds a reference to an image
  81. // with the same depth and size of the input image; this image
  82. // will be used as temporary processing buffer in the chain of
  83. // operators in an expression. Must be a non empty image.
  84. //
  85. // dst : A modifiable reference to a smart-reference image container.
  86. // On input, assumed to be an empty matrix for the first operator
  87. // in the chain of operators in an expression; for remaing calls,
  88. // a reference to the buffer returned by the first operator in
  89. // rhs. On output, the result of a successful operation.
  90. //
  91. virtual void apply(matrix& dst, matrix& src, bool const first) = 0;
  92.  
  93. // clone this operator
  94. //
  95. virtual opnode_t clone() const = 0;
  96.  
  97. friend matrix operator*(i_operator& lhs_op, matrix const& rhs_im);
  98.  
  99. friend class operator_expression;
  100.  
  101. };
  102.  
  103.  
  104. // Tool for checking i_operator implementation
  105. //
  106.  
  107. template<typename T>
  108. class is_operator
  109. {
  110. public:
  111.  
  112. static auto constexpr value = std::is_base_of<i_operator, T>::value;
  113.  
  114. };
  115.  
  116.  
  117. // Interface for operator predicates
  118. //
  119.  
  120. class i_operator_predicate
  121. {
  122. public:
  123.  
  124. //virtual bool supported(matrix const& mat) const noexcept = 0;
  125.  
  126. virtual void do_apply(matrix& dst, matrix& src, bool const first) = 0;
  127.  
  128. template<typename ...Args>
  129. void reset(Args&& ...arg);
  130.  
  131. };
  132.  
  133.  
  134. // Tool for checking i_operator_predicate implementation
  135. //
  136.  
  137. template<typename P>
  138. class is_operator_predicate
  139. {
  140. private:
  141.  
  142. struct has_member { char z[1]; };
  143. struct no_member { char z[2]; };
  144.  
  145. //template<typename T> static has_member has_supported_member(decltype(&T::supported));
  146. template<typename T> static has_member has_do_apply_member(decltype(&T::do_apply));
  147.  
  148. //template<typename T> static no_member has_supported_member(...);
  149. template<typename T> static no_member has_do_apply_member(...);
  150.  
  151. static auto constexpr yes = sizeof(has_member);
  152. //static auto constexpr has_supported = sizeof(has_supported_member<P>(nullptr));
  153. static auto constexpr has_do_apply = sizeof(has_do_apply_member<P>(nullptr));
  154. static auto constexpr is_predicate = std::is_base_of<i_operator_predicate, P>::value;
  155.  
  156. public:
  157.  
  158. static auto constexpr value = is_predicate
  159. or /*has_supported == yes and*/ has_do_apply == yes;
  160.  
  161. };
  162.  
  163. }
  164.  
  165. }
  166.  
  167. // operator.hpp
  168.  
  169.  
  170. namespace cvip
  171. {
  172.  
  173. namespace core
  174. {
  175.  
  176. // Generic abstract base class for image matrix operators, partially
  177. // implements i_operator providing cloning facility via CRT Pattern.
  178. //
  179.  
  180. template<typename ConcreteOperator>
  181. class base_operator : public i_operator
  182. {
  183. public:
  184.  
  185. base_operator() noexcept = default;
  186.  
  187. base_operator(base_operator const& src) noexcept = default;
  188.  
  189. base_operator(base_operator&& src) noexcept = default;
  190.  
  191. virtual ~base_operator() noexcept = default;
  192.  
  193. base_operator& operator=(base_operator const& src) noexcept = default;
  194.  
  195. base_operator& operator=(base_operator&& src) noexcept = default;
  196.  
  197.  
  198. protected:
  199.  
  200. using operator_t = ConcreteOperator;
  201.  
  202. virtual opnode_t clone() const override;
  203.  
  204. };
  205.  
  206.  
  207. // Predicate based image operator
  208. //
  209.  
  210. template<typename Predicate>
  211. class basic_operator : public base_operator< basic_operator<Predicate> >
  212. {
  213. public:
  214.  
  215. template<typename ...Args>
  216. basic_operator(Args&& ...arg);
  217.  
  218. template<typename ...Args>
  219. basic_operator& operator()(Args&& ...arg);
  220.  
  221.  
  222. protected:
  223.  
  224. virtual void apply(matrix& dst, matrix& src, bool const first) override;
  225.  
  226.  
  227. private:
  228.  
  229. using predicate_t = Predicate;
  230.  
  231. static_assert(is_operator_predicate<predicate_t>::value,
  232. "predicate_t does not implement i_operator_predicate");
  233.  
  234.  
  235. private:
  236.  
  237. predicate_t m_operation = { };
  238.  
  239. };
  240.  
  241. }
  242.  
  243. }
  244.  
  245. // operator.inl
  246.  
  247. #include <memory>
  248. #include <utility>
  249.  
  250. namespace cvip
  251. {
  252.  
  253. namespace core
  254. {
  255.  
  256. // base_operator<ConcreteOperator>
  257. //
  258.  
  259. template<typename ConcreteOperator>
  260. inline typename base_operator<ConcreteOperator>::opnode_t base_operator<ConcreteOperator>::clone() const
  261. {
  262. static_assert(is_operator<operator_t>::value, "operator_t is not an i_operator");
  263. return std::make_shared<operator_t>(*static_cast<operator_t const*>(this));
  264. }
  265.  
  266.  
  267. // basic_operator<Predicate>
  268. //
  269.  
  270. template<typename Predicate> template<typename ...Args>
  271. basic_operator<Predicate>::basic_operator(Args&& ...arg) :
  272. m_operation{ std::forward<Args>(arg)... }
  273. {
  274. // NOOP
  275. }
  276.  
  277. template<typename Predicate> template<typename ...Args>
  278. inline basic_operator<Predicate>& cvip::core::basic_operator<Predicate>::operator()(Args&& ...arg)
  279. {
  280. return (m_operation.reset(std::forward<Args>(arg)...), *this);
  281. }
  282.  
  283. template<typename Predicate>
  284. inline void basic_operator<Predicate>::apply(matrix& dst, matrix& src, bool const first)
  285. {
  286. m_operation.do_apply(dst, src, first);
  287. }
  288.  
  289.  
  290. // image operator operations
  291. //
  292.  
  293. inline matrix operator*(i_operator&& lhs_op, matrix const& rhs_im)
  294. {
  295. return lhs_op * rhs_im;
  296. }
  297.  
  298. }
  299.  
  300. }
  301.  
  302. // operator.cpp
  303.  
  304. namespace cvip
  305. {
  306.  
  307. namespace core
  308. {
  309.  
  310. matrix operator*(i_operator& lhs_op, matrix const& rhs_im)
  311. {
  312. auto src = matrix{ rhs_im };
  313. auto dst = matrix{ };
  314.  
  315. lhs_op.apply(dst, src, true);
  316.  
  317. return dst;
  318. }
  319.  
  320. }
  321.  
  322. }
  323.  
  324. // expression.hpp
  325.  
  326. #include <list>
  327. #include <memory>
  328.  
  329. namespace cvip
  330. {
  331.  
  332. // Operator expressions
  333. //
  334. // The built-int multiplication operator (operator*) is used to indicate
  335. // operations among image operators and image matrices.
  336. //
  337. // Arithmetic operation among operators and matrices is done from right to
  338. // left, nevertheless, operation among operators are gathered from left to
  339. // right within an operator expression.
  340. //
  341. // Applying an operator, P, on a matrix, M1, produces a new matrix, M2:
  342. //
  343. // P * M1 -> M2.
  344. //
  345. // Applying an operator, P2, on another operator, P1, produces an operator
  346. // expression that gather both operators for later application in the
  347. // appropriate order:
  348. //
  349. // P2 * P1 -> EX(P1, P2).
  350. //
  351. // Applying an operator expression on a matrix, M1, produces a new matrix,
  352. // M2, after applying the encapsulated operators in the correct order:
  353. //
  354. // EX(P1, P2) * M1 -> M2.
  355. //
  356. // Applying an operator expression on an operator, P3, produces a new
  357. // operator expression concatenating it with the existing operators in the
  358. // proper order:
  359. //
  360. // EX(P1, P2) * P3 -> EX(P3, P1, P2).
  361. //
  362. // Applying an operator expression on another operator expression, produces
  363. // a new operator expression concatenating the existing operators in the
  364. // proper order:
  365. //
  366. // EX(P1, P2) * EX(P3, P4) -> EX(P3, P4, P1, P2).
  367. //
  368. // The commutative property does not hold for operators and operator
  369. // expressions:
  370. //
  371. // P2 * P1 -> EX(P1, P2),
  372. // P1 * P2 -> EX(P2, P1),
  373. //
  374. // EX(P1, P2) * P3 -> EX(P3, P1, P2),
  375. // P3 * EX(P1, P2) -> EX(P1, P2, P3),
  376. //
  377. // EX(P1, P2) * EX(P3, P4) -> EX(P3, P4, P1, P2),
  378. // EX(P3, P4) * EX(P1, P2) -> EX(P1, P2, P3, P4).
  379. //
  380. // Associative property among operators and operator expressions is just
  381. // syntactic sugar and is implemented for semantic purposes, e.g. for
  382. // grouping or emphasise related operations. The following operations are
  383. // the same:
  384. //
  385. // (P1 * P2) * P3 * M === P1 * P2 * P3 * M,
  386. //
  387. // however, the next operations are equivalent, i.e. they produce the same
  388. // result but the intermediate products are not the same:
  389. //
  390. // (P1 * P2) * P3 * M == P1 * (P2 * P3) * M,
  391. //
  392. // but
  393. //
  394. // (P1 * P2) * P3 * M !== P1 * (P2 * P3) * M.
  395. //
  396. // Listing the intermediate results, we have:
  397. //
  398. // Example 1.
  399. //
  400. // 1) P3 * P2 * P1 * M1 ... or (P3 * P2) * P1 * M1
  401. // 2) EX(P2, P3) * P1 * M1
  402. // 3) EX(P1, P2, P3) * M1 ... operators are applied in the order
  403. // 4) M2 ... P1, P2, and P3
  404. //
  405. // Example 2.
  406. //
  407. // 1) P3 * (P2 * P1) * M1
  408. // 2) P3 * EX(P1, P2) * M1
  409. // 3) EX(P1, P2, P3) * M1 ... operators are applied in the order
  410. // 4) M2 ... P1, P2, and P3
  411. //
  412. // Example 3.
  413. //
  414. // 1) P4 * P3 * (P2 * P1) * M1
  415. // 2) P4 * P3 * EX(P1, P2) * M1
  416. // 3) EX(P3, P4) * EX(P1, P2) * M1
  417. // 4) EX(P1, P2, P3, P4) * M1
  418. // 5) M2
  419. //
  420. // Example 4.
  421. //
  422. // 1) (P4 * P3) * (P2 * P1) * M1
  423. // 2) EX(P3, P4) * (P2 * P1) * M1
  424. // 3) EX(P3, P4) * EX(P1, P2) * M1
  425. // 4) EX(P1, P2, P3, P4) * M1
  426. // 5) M2
  427. //
  428. // Provided the operators are equivalent, Example 1 and Example 2, and
  429. // Example 3 and Example 4, respectively, produce the same result.
  430. //
  431. // Applying association to operators or operator expressions and matrices,
  432. // force the application of the gathered operators to the image and
  433. // produces a new intermediate image before continuing with the remaning
  434. // operators:
  435. //
  436. // Example 5.
  437. //
  438. // 1) P3 * P2 * (P1 * M1)
  439. // 2) P3 * P2 * M2
  440. // 3) EX(P2, P3) * M2
  441. // 4) M3
  442. //
  443. // Even though, if the operators are equivalent, Example 1 and Example 5,
  444. // produce the same result.
  445. //
  446.  
  447. namespace core
  448. {
  449.  
  450. //class operator_expression;
  451.  
  452. //operator_expression operator*(i_operator const& lhs_op, i_operator const& rhs_op);
  453.  
  454. //operator_expression operator*(operator_expression&& lhs_ex, i_operator const& rhs_op);
  455.  
  456. //operator_expression operator*(i_operator const& lhs_op, operator_expression&& rhs_ex);
  457.  
  458. //operator_expression operator*(operator_expression&& lhs_ex, operator_expression&& rhs_ex);
  459.  
  460. //matrix operator*(operator_expression& lhs_ex, matrix const& rhs_im);
  461.  
  462. // Operator expression
  463. //
  464. // Allows operator semantics for image matrix operations. Operations
  465. // among image operators and image matrices are right associative,
  466. // while operations among operators are left associative.
  467. //
  468.  
  469. class operator_expression
  470. {
  471. public:
  472.  
  473. operator_expression() = delete;
  474.  
  475. operator_expression(operator_expression const& src) noexcept = default;
  476.  
  477. operator_expression(operator_expression&& src) noexcept = default;
  478.  
  479. ~operator_expression() noexcept = default;
  480.  
  481. operator_expression& operator=(operator_expression const& src) noexcept = default;
  482.  
  483. operator_expression& operator=(operator_expression&& src) noexcept = default;
  484.  
  485.  
  486. private:
  487.  
  488. operator_expression(i_operator const& lhs_op, i_operator const& rhs_op);
  489.  
  490.  
  491. private:
  492.  
  493. matrix apply(matrix const& rhs_im);
  494.  
  495. void emplace_back(operator_expression&& lhs_ex);
  496.  
  497. void push_back(i_operator const& lhs_op);
  498.  
  499. void push_front(i_operator const& rhs_op);
  500.  
  501.  
  502. private:
  503.  
  504. friend operator_expression operator*(i_operator const& lhs_op, i_operator const& rhs_op);
  505.  
  506. friend operator_expression operator*(operator_expression&& lhs_ex, i_operator const& rhs_op);
  507.  
  508. friend operator_expression operator*(i_operator const& lhs_op, operator_expression&& rhs_ex);
  509.  
  510. friend operator_expression operator*(operator_expression&& lhs_ex, operator_expression&& rhs_ex);
  511.  
  512. friend matrix operator*(operator_expression& lhs_ex, matrix const& rhs_im);
  513.  
  514.  
  515. private:
  516.  
  517. using opnode_t = i_operator::opnode_t;
  518. using opchain_t = std::list<opnode_t>;
  519. using exdata_t = std::shared_ptr<opchain_t>;
  520.  
  521.  
  522. private:
  523.  
  524. exdata_t construct_data(i_operator const& lhs_op, i_operator const& rhs_op);
  525.  
  526.  
  527. private:
  528.  
  529. exdata_t m_data = { };
  530.  
  531. };
  532.  
  533. }
  534.  
  535. }
  536.  
  537. // expression.inl
  538.  
  539. #include <utility>
  540.  
  541. namespace cvip
  542. {
  543.  
  544. namespace core
  545. {
  546.  
  547. // operator_expression
  548. //
  549.  
  550. inline void operator_expression::emplace_back(operator_expression&& lhs_ex)
  551. {
  552. m_data->splice(m_data->end(), std::move(*lhs_ex.m_data));
  553. }
  554.  
  555. inline void operator_expression::push_back(i_operator const& lhs_op)
  556. {
  557. m_data->emplace_back(lhs_op.clone());
  558. }
  559.  
  560. inline void operator_expression::push_front(i_operator const& rhs_op)
  561. {
  562. m_data->emplace_front(rhs_op.clone());
  563. }
  564.  
  565.  
  566. // operator_expression operator* (op * op)
  567. //
  568.  
  569. inline operator_expression operator*(i_operator const& lhs_op, i_operator const& rhs_op)
  570. {
  571. return { lhs_op, rhs_op };
  572. }
  573.  
  574.  
  575. // operator_expression operator* (ex * op, op * ex)
  576. //
  577.  
  578. inline operator_expression operator*(operator_expression&& lhs_ex, i_operator const& rhs_op)
  579. {
  580. return (lhs_ex.push_front(rhs_op), std::move(lhs_ex));
  581. }
  582.  
  583. inline operator_expression operator*(i_operator const& lhs_op, operator_expression&& rhs_ex)
  584. {
  585. return (rhs_ex.push_back(lhs_op), std::move(rhs_ex));
  586. }
  587.  
  588. inline operator_expression operator*(operator_expression const& lhs_ex, i_operator const& rhs_op)
  589. {
  590. return operator_expression{ lhs_ex } * rhs_op;
  591. }
  592.  
  593. inline operator_expression operator*(i_operator const& lhs_op, operator_expression const& rhs_ex)
  594. {
  595. return lhs_op * operator_expression{ rhs_ex };
  596. }
  597.  
  598.  
  599. // operator_expression operator* (ex * ex)
  600. //
  601.  
  602. inline operator_expression operator*(operator_expression&& lhs_ex, operator_expression&& rhs_ex)
  603. {
  604. return (rhs_ex.emplace_back(std::move(lhs_ex)), std::move(rhs_ex));
  605. }
  606.  
  607. inline operator_expression operator*(operator_expression&& lhs_ex, operator_expression const& rhs_ex)
  608. {
  609. return std::move(lhs_ex) * operator_expression{ rhs_ex };
  610. }
  611.  
  612. inline operator_expression operator*(operator_expression const& lhs_ex, operator_expression&& rhs_ex)
  613. {
  614. return operator_expression{ lhs_ex } * std::move(rhs_ex);
  615. }
  616.  
  617. inline operator_expression operator*(operator_expression const& lhs_ex, operator_expression const& rhs_ex)
  618. {
  619. return operator_expression{ lhs_ex } * operator_expression{ rhs_ex };
  620. }
  621.  
  622. inline matrix operator*(operator_expression& lhs_ex, matrix const& rhs_im)
  623. {
  624. return lhs_ex.apply(rhs_im);
  625. }
  626.  
  627. inline matrix operator*(operator_expression&& lhs_ex, matrix const& rhs_im)
  628. {
  629. return lhs_ex * rhs_im;
  630. }
  631.  
  632. }
  633.  
  634. }
  635.  
  636. // expression.cpp
  637.  
  638. #include <initializer_list>
  639. #include <cassert>
  640.  
  641. namespace cvip
  642. {
  643.  
  644. namespace core
  645. {
  646.  
  647. operator_expression::operator_expression(i_operator const& lhs_op, i_operator const& rhs_op) :
  648. m_data{ construct_data(lhs_op, rhs_op) }
  649. {
  650. assert(m_data.use_count() == 1);
  651. }
  652.  
  653. matrix operator_expression::apply(matrix const& rhs_im)
  654. {
  655. auto src = matrix{ rhs_im };
  656. auto dst = matrix{ };
  657.  
  658. auto first = true;
  659.  
  660. for (auto& op : *m_data)
  661. {
  662. op->apply(dst, src, first);
  663.  
  664. cv::swap(dst, src);
  665.  
  666. first = false;
  667. }
  668.  
  669. // REMARK: The result is in src due to the swap
  670. // at the end of each iteration!
  671.  
  672. return src;
  673. }
  674.  
  675. inline operator_expression::exdata_t operator_expression::construct_data(i_operator const& lhs_op,
  676. i_operator const& rhs_op)
  677. {
  678. return std::make_shared<opchain_t>(opchain_t{ rhs_op.clone(), lhs_op.clone() });
  679. }
  680.  
  681. }
  682.  
  683. }
  684.  
  685. // test entry-point
  686.  
  687. #include <iostream>
  688.  
  689. using namespace std;
  690.  
  691. int main()
  692. {
  693. std::cout << "Hello world!";
  694.  
  695. return 0;
  696. }
  697.  
  698. // struct i_op
  699.  
  700.  
  701. // using opnode_t = i_operator::opnode_t;
  702. // using opchain_t = std::list<opnode_t>;
  703. // using exdata_t = std::shared_ptr<opchain_t>;
  704. //
  705.  
Success #stdin #stdout 0.01s 5360KB
stdin
Standard input is empty
stdout
Hello world!