Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit149e4f7

Browse files
committed
add n-dimensional transpose to core
1 parent8fa429c commit149e4f7

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed

‎modules/core/include/opencv2/core.hpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,6 +1739,13 @@ should be done separately if needed.
17391739
*/
17401740
CV_EXPORTS_Wvoidtranspose(InputArray src, OutputArray dst);
17411741

1742+
/** @brief Transpose for n-dimensional matrices.
1743+
* @param src input array.
1744+
* @param order new order of dimensions.
1745+
* @param dst output array of the same type as src.
1746+
*/
1747+
CV_EXPORTS_Wvoidtranspose(const Mat& src,const std::vector<int>& order, OutputArray dst);
1748+
17421749
/** @brief Performs the matrix transformation of every array element.
17431750
17441751
The function cv::transform performs the matrix transformation of every

‎modules/core/src/matrix_transform.cpp‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include"precomp.hpp"
66
#include"opencl_kernels_core.hpp"
7+
#include"opencv2/core/detail/dispatch_helper.impl.hpp"
78

89
namespacecv {
910

@@ -282,6 +283,69 @@ void transpose( InputArray _src, OutputArray _dst )
282283
}
283284

284285

286+
287+
template<typename T>
288+
structtransposeImpl
289+
{
290+
voidoperator()(const cv::Mat& inp, cv::Mat& out,const std::vector<int>& order)const
291+
{
292+
int continuous_idx =0;
293+
for (int i =static_cast<int>(order.size()) -1; i >=0; --i)
294+
{
295+
if (order[i] != i)
296+
{
297+
continuous_idx = i +1;
298+
break;
299+
}
300+
}
301+
302+
size_t continuous_size = continuous_idx ==0 ? out.total() : out.step1(continuous_idx -1);
303+
size_t outer_size = out.total() / continuous_size;
304+
305+
std::vector<size_t>steps(order.size());
306+
for (int i =0; i <static_cast<int>(steps.size()); ++i)
307+
{
308+
steps[order[i]] = out.step1(i);
309+
}
310+
311+
auto* src = inp.ptr<const T>();
312+
auto* dst = out.ptr<T>();
313+
314+
size_t dst_offset =0;
315+
for (size_t i =0; i < outer_size; ++i)
316+
{
317+
std::memcpy(dst + dst_offset, src, out.elemSize() * continuous_size);
318+
src += continuous_size;
319+
for (int j = continuous_idx -1; j >=0; --j)
320+
{
321+
dst_offset += steps[j];
322+
if ((dst_offset / steps[j]) % inp.size[j] !=0)
323+
{
324+
break;
325+
}
326+
dst_offset -= steps[j] * inp.size[j];
327+
}
328+
}
329+
}
330+
};
331+
332+
voidtranspose(const Mat& inp,const std::vector<int>& order, OutputArray _out)
333+
{
334+
CV_Assert(inp.isContinuous() && inp.channels() ==1);
335+
336+
std::vector<int>newShape(order.size());
337+
for (size_t i =0; i < order.size(); ++i)
338+
{
339+
newShape[i] = inp.size[order[i]];
340+
}
341+
342+
_out.create(static_cast<int>(newShape.size()), newShape.data(), inp.type());
343+
Mat out = _out.getMat();
344+
CV_Assert(out.isContinuous());// does OutputArray::create always returns continuous matrix?
345+
cv::detail::depthDispatch<transposeImpl>(inp.depth(), inp, out, order);
346+
}
347+
348+
285349
#if CV_SIMD128
286350
template<typename V> CV_ALWAYS_INLINEvoidflipHoriz_single(const uchar* src,size_t sstep, uchar* dst,size_t dstep, Size size,size_t esz )
287351
{

‎modules/core/test/test_arithm.cpp‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// of this distribution and at http://opencv.org/license.html.
44
#include"test_precomp.hpp"
55
#include"ref_reduce_arg.impl.hpp"
6+
#include<algorithm>
67

78
namespaceopencv_test {namespace {
89

@@ -2128,6 +2129,80 @@ TEST(Core_minMaxIdx, regression_9207_1)
21282129
}
21292130

21302131

2132+
classTransposeND :publictesting::TestWithParam< tuple<std::vector<int>, perf::MatType> >
2133+
{
2134+
public:
2135+
std::vector<int> m_shape;
2136+
int m_type;
2137+
2138+
voidSetUp()
2139+
{
2140+
std::tie(m_shape, m_type) =GetParam();
2141+
}
2142+
};
2143+
2144+
2145+
TEST_P(TransposeND, basic)
2146+
{
2147+
setRNGSeed(42);
2148+
Matinp(m_shape, m_type);
2149+
randu(inp,0,255);
2150+
2151+
std::vector<int>order(m_shape.size());
2152+
std::iota(order.begin(), order.end(),0);
2153+
auto transposer = [&order] (const std::vector<int>& id)
2154+
{
2155+
std::vector<int>ret(id.size());
2156+
for (size_t i =0; i < id.size(); ++i)
2157+
{
2158+
ret[i] = id[order[i]];
2159+
}
2160+
return ret;
2161+
};
2162+
auto advancer = [&inp] (std::vector<int>& id)
2163+
{
2164+
for (int j = id.size() -1; j >=0; --j)
2165+
{
2166+
++id[j];
2167+
if (id[j] != inp.size[j])
2168+
{
2169+
break;
2170+
}
2171+
id[j] =0;
2172+
}
2173+
};
2174+
2175+
do
2176+
{
2177+
Mat out;
2178+
cv::transpose(inp, order, out);
2179+
std::vector<int>id(order.size());
2180+
for (size_t i =0; i < inp.total(); ++i)
2181+
{
2182+
auto new_id =transposer(id);
2183+
switch (inp.type())
2184+
{
2185+
case CV_8UC1:
2186+
CV_Assert(inp.at<uint8_t>(id.data()) == out.at<uint8_t>(new_id.data()));
2187+
break;
2188+
case CV_32FC1:
2189+
CV_Assert(inp.at<float>(id.data()) == out.at<float>(new_id.data()));
2190+
break;
2191+
default:
2192+
CV_Error(Error::StsBadArg,format("Unsupported type: %d", inp.type()));
2193+
}
2194+
advancer(id);
2195+
}
2196+
}while (std::next_permutation(order.begin(), order.end()));
2197+
}
2198+
2199+
2200+
INSTANTIATE_TEST_CASE_P(Arithm, TransposeND, testing::Combine(
2201+
testing::Values(std::vector<int>{2,3,4}, std::vector<int>{5,10}),
2202+
testing::Values(perf::MatType(CV_8UC1), CV_32FC1)
2203+
));
2204+
2205+
21312206
TEST(Core_minMaxIdx, regression_9207_2)
21322207
{
21332208
constint rows =13;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp