vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e

This commit is contained in:
Gitea Mirror Bot
2026-08-22 00:11:13 +08:00
commit 12022378a3
3872 changed files with 2513409 additions and 0 deletions
+236
View File
@@ -0,0 +1,236 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
#include <iostream>
namespace
{
class DefaultAllocator : public cv::cann::AscendMat::Allocator
{
public:
std::shared_ptr<uchar> allocate(size_t size) CV_OVERRIDE;
bool allocate(cv::cann::AscendMat* mat, int rows, int cols, size_t elemSize) CV_OVERRIDE;
};
std::shared_ptr<uchar> DefaultAllocator::allocate(size_t size)
{
uchar* data;
cv::cann::aclrtMallocWarpper((void**)(&data), size);
return std::shared_ptr<uchar>(data, [](void* ptr) { cv::cann::aclrtFreeWarpper(ptr); });
}
bool DefaultAllocator::allocate(cv::cann::AscendMat* mat, int rows, int cols, size_t elemSize)
{
size_t totalBytes = elemSize * cols * rows;
// align by 32B.
totalBytes = ((totalBytes + 32) & ~31);
mat->data = allocate(totalBytes);
mat->step = cols * elemSize;
return true;
}
DefaultAllocator cannDefaultAllocator;
cv::cann::AscendMat::Allocator* g_defaultAllocator = &cannDefaultAllocator;
} // namespace
namespace cv
{
namespace cann
{
AscendMat::Allocator* AscendMat::defaultAllocator() { return g_defaultAllocator; }
void AscendMat::setDefaultAllocator(AscendMat::Allocator* allocator)
{
CV_Assert(allocator != 0);
g_defaultAllocator = allocator;
}
// TODO: this function is copied from matrix.cpp, which is a local symbol there and can not
// be refreneced, consider optimizing.
static int updateContinuityFlag(int flags, int dims, const int* size, const size_t* step)
{
int i, j;
for (i = 0; i < dims; i++)
{
if (size[i] > 1)
break;
}
uint64 t = (uint64)size[std::min(i, dims - 1)] * CV_MAT_CN(flags);
for (j = dims - 1; j > i; j--)
{
t *= size[j];
if (step[j] * size[j] < step[j - 1])
break;
}
if (j <= i && t == (uint64)(int)t)
return flags | Mat::CONTINUOUS_FLAG;
return flags & ~Mat::CONTINUOUS_FLAG;
}
void AscendMat::updateContinuityFlag()
{
int sz[] = {rows, cols};
size_t steps[] = {step, elemSize()};
flags = cv::cann::updateContinuityFlag(flags, 2, sz, steps);
}
void AscendMat::create(int _rows, int _cols, int _type)
{
CV_DbgAssert(_rows >= 0 && _cols >= 0);
_type &= Mat::TYPE_MASK;
if (rows == _rows && cols == _cols && type() == _type && data)
return;
if (_rows > 0 && _cols > 0)
{
flags = Mat::MAGIC_VAL + _type;
rows = _rows;
cols = _cols;
const size_t esz = elemSize();
bool allocSuccess = allocator->allocate(this, rows, cols, esz);
if (!allocSuccess)
{
// custom allocator fails, try default allocator
allocator = defaultAllocator();
allocSuccess = allocator->allocate(this, rows, cols, esz);
CV_Assert(allocSuccess);
}
if (esz * cols == step)
flags |= Mat::CONTINUOUS_FLAG;
datastart = data.get();
dataend = data.get() + step * (rows - 1) + cols * esz;
}
}
void AscendMat::upload(InputArray arr) { upload(arr, AscendStream::Null()); }
void AscendMat::upload(InputArray arr, AscendStream& stream)
{
Mat mat = arr.getMat();
CV_DbgAssert(!mat.empty());
create(mat.rows, mat.cols, mat.type());
aclrtMemcpy2dWarpper(data, 0, step, mat.data, mat.step[0], cols * elemSize(), rows, stream);
}
void AscendMat::download(OutputArray dst) const { download(dst, AscendStream::Null()); }
void AscendMat::download(OutputArray _dst, AscendStream& stream) const
{
CV_DbgAssert(!empty());
_dst.create(size(), type());
Mat dst = _dst.getMat();
aclrtMemcpy2dWarpper(dst.data, dst.step[0], data, 0, step, cols * elemSize(), rows, stream);
}
AscendMat::AscendMat(int rows_, int cols_, int type_, Scalar& s_, AscendMat::Allocator* allocator_)
: flags(0), rows(rows_), cols(cols_), step(0), datastart(0), dataend(0), allocator(allocator_)
{
create(rows_, cols_, type_);
setTo(s_);
}
AscendMat::AscendMat(Size size_, int type_, Scalar& s_, AscendMat::Allocator* allocator_)
: flags(0), rows(size_.height), cols(size_.width), step(0), datastart(0), dataend(0),
allocator(allocator_)
{
create(size_.height, size_.width, type_);
setTo(s_);
}
AscendMat::AscendMat(InputArray _m, const Rect& roi) : AscendMat(_m, roi, AscendStream::Null()) {}
AscendMat::AscendMat(InputArray _m, const Rect& roi, AscendStream& stream)
: rows(roi.height), cols(roi.width), allocator(defaultAllocator())
{
AscendMat m;
m.upload(_m, stream);
step = m.step;
data = m.data;
flags = m.flags;
CV_Assert(0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y &&
0 <= roi.height && roi.y + roi.height <= m.rows);
size_t esz = CV_ELEM_SIZE(flags);
size_t sizeMem = esz * roi.width * roi.height * m.channels();
size_t offset = roi.y * m.step + roi.x * esz;
void* dst = malloc(sizeMem);
size_t dpitch = roi.width * esz;
std::shared_ptr<uchar> dstDevice = allocator->allocate(sizeMem);
aclrtMemcpy2dWarpper(dst, dpitch, data, offset, step, dpitch, roi.height, stream);
aclrtMemcpy2dWarpper(dstDevice, 0, dpitch, dst, dpitch, dpitch, roi.height, stream);
data = dstDevice;
step = dpitch;
free(dst);
updateContinuityFlag();
}
AscendMat& AscendMat::setTo(const Scalar& sc) { return setTo(sc, AscendStream::Null()); }
AscendMat& AscendMat::setTo(const Scalar& sc, AscendStream& stream)
{
size_t totalBytes = (size_t)rows * cols * elemSize();
if (totalBytes == 0)
return *this;
aclrtMemsetWarpper(data, 0, totalBytes, stream);
AscendMat dst(rows, cols, type());
arithm_op(*this, sc, dst, "Add", stream);
swap(dst);
return *this;
}
AscendMat& AscendMat::setTo(float sc) { return setTo(sc, AscendStream::Null()); }
AscendMat& AscendMat::setTo(float sc, AscendStream& stream)
{
size_t totalBytes = (size_t)rows * cols * elemSize();
if (totalBytes == 0)
return *this;
aclrtMemsetWarpper(data, 0, totalBytes, stream);
AscendMat dst(rows, cols, type());
arithm_op(*this, sc, dst, "Adds", stream);
swap(dst);
return *this;
}
void AscendMat::convertTo(AscendMat& dst, int rtype) const
{
convertTo(dst, rtype, AscendStream::Null());
}
void AscendMat::convertTo(AscendMat& dst, int _rtype, AscendStream& stream) const
{
int cn = channels();
dst.create(rows, cols, CV_MAKE_TYPE(_rtype, cn));
convertTo(dst, stream);
}
void AscendMat::convertTo(AscendMat& dst, AscendStream& stream) const
{
OperatorRunner runner;
runner.setOp("Cast")
.addInput(*this, "x")
.addOutput(dst, "y")
.addAttr((int32_t)(getACLType(dst.depth())), "dst_type")
.run(stream);
}
} // namespace cann
} // namespace cv
+516
View File
@@ -0,0 +1,516 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include <acl/acl.h>
#include <acl/acl_op_compiler.h>
#include "precomp.hpp"
#include "opencv2/core/private.hpp"
namespace cv
{
namespace cann
{
/*******************************Acl Error Checker*****************************/
void checkAclError(aclError err, const char* file, const int line, const char* func)
{
if (ACL_SUCCESS != err)
{
const char* errMsg = aclGetRecentErrMsg();
cv::error(cv::Error::StsError, errMsg == nullptr ? "" : errMsg, func, file, line);
}
}
void checkAclPtr(void* ptr, const char* file, const int line, const char* func)
{
if (nullptr == ptr)
{
const char* errMsg = aclGetRecentErrMsg();
cv::error(cv::Error::StsError, errMsg == nullptr ? "" : errMsg, func, file, line);
}
}
/******************************Acl Runtime Warpper****************************/
void aclrtMallocWarpper(void** data, size_t size)
{
CV_ACL_SAFE_CALL(aclrtMalloc(data, size, ACL_MEM_MALLOC_HUGE_FIRST));
}
void aclrtFreeWarpper(void* data) { CV_ACL_SAFE_CALL(aclrtFree(data)); }
void aclrtMemcpyWarpper(std::shared_ptr<uchar>& dst, size_t offset, const void* src, size_t size,
AscendStream& stream)
{
aclrtStream rawStream = AscendStreamAccessor::getStream(stream);
if (rawStream == nullptr)
CV_ACL_SAFE_CALL(
aclrtMemcpy(dst.get() + offset, size, src, size, ACL_MEMCPY_HOST_TO_DEVICE));
else
{
CV_ACL_SAFE_CALL(aclrtMemcpyAsync(dst.get() + offset, size, src, size,
ACL_MEMCPY_HOST_TO_DEVICE, rawStream));
if (offset == 0)
stream.addTensorHolder(dst);
}
}
void aclrtMemcpyWarpper(void* dst, const std::shared_ptr<uchar>& src, size_t offset, size_t size,
AscendStream& stream)
{
aclrtStream rawStream = AscendStreamAccessor::getStream(stream);
if (rawStream == nullptr)
CV_ACL_SAFE_CALL(
aclrtMemcpy(dst, size, src.get() + offset, size, ACL_MEMCPY_DEVICE_TO_HOST));
else
{
CV_ACL_SAFE_CALL(aclrtMemcpyAsync(dst, size, src.get() + offset, size,
ACL_MEMCPY_DEVICE_TO_HOST, rawStream));
if (offset == 0)
stream.addTensorHolder(src);
}
}
void aclrtMemcpyWarpper(std::shared_ptr<uchar>& dst, size_t dstOffset,
const std::shared_ptr<uchar>& src, size_t srcOffset, size_t size,
AscendStream& stream)
{
aclrtStream rawStream = AscendStreamAccessor::getStream(stream);
if (rawStream == nullptr)
CV_ACL_SAFE_CALL(aclrtMemcpy(dst.get() + dstOffset, size, src.get() + srcOffset, size,
ACL_MEMCPY_DEVICE_TO_DEVICE));
else
{
CV_ACL_SAFE_CALL(aclrtMemcpyAsync(dst.get() + dstOffset, size, src.get() + srcOffset, size,
ACL_MEMCPY_DEVICE_TO_DEVICE, rawStream));
if (srcOffset == 0)
stream.addTensorHolder(src);
if (dstOffset == 0)
stream.addTensorHolder(dst);
}
}
void aclrtMemcpy2dWarpper(std::shared_ptr<uchar>& dst, size_t offset, size_t dpitch,
const void* src, size_t spitch, size_t width, size_t length,
AscendStream& stream)
{
aclrtStream rawStream = AscendStreamAccessor::getStream(stream);
if (rawStream == nullptr)
CV_ACL_SAFE_CALL(aclrtMemcpy2d(dst.get() + offset, dpitch, src, spitch, width, length,
ACL_MEMCPY_HOST_TO_DEVICE));
else
{
CV_ACL_SAFE_CALL(aclrtMemcpy2dAsync(dst.get() + offset, dpitch, src, spitch, width, length,
ACL_MEMCPY_HOST_TO_DEVICE, rawStream));
stream.addTensorHolder(dst);
}
}
void aclrtMemcpy2dWarpper(void* dst, size_t dpitch, const std::shared_ptr<uchar>& src,
size_t offset, size_t spitch, size_t width, size_t length,
AscendStream& stream)
{
aclrtStream rawStream = AscendStreamAccessor::getStream(stream);
if (rawStream == nullptr)
CV_ACL_SAFE_CALL(aclrtMemcpy2d(dst, dpitch, src.get() + offset, spitch, width, length,
ACL_MEMCPY_DEVICE_TO_HOST));
else
{
CV_ACL_SAFE_CALL(aclrtMemcpy2dAsync(dst, dpitch, src.get() + offset, spitch, width, length,
ACL_MEMCPY_DEVICE_TO_HOST, rawStream));
stream.addTensorHolder(src);
}
}
void aclrtMemsetWarpper(std::shared_ptr<uchar>& ptr, int32_t value, size_t count,
AscendStream& stream)
{
aclrtStream rawStream = AscendStreamAccessor::getStream(stream);
if (rawStream == nullptr)
CV_ACL_SAFE_CALL(aclrtMemset(ptr.get(), count, value, count));
else
{
CV_ACL_SAFE_CALL(aclrtMemsetAsync(ptr.get(), count, value, count, rawStream));
stream.addTensorHolder(ptr);
}
}
aclDataType getACLType(int opencvdepth)
{
switch (opencvdepth)
{
case CV_8S:
return ACL_INT8;
case CV_16S:
return ACL_INT16;
case CV_8U:
return ACL_UINT8;
case CV_16U:
return ACL_UINT16;
case CV_32S:
return ACL_INT32;
case CV_32F:
return ACL_FLOAT;
case CV_64F:
return ACL_DOUBLE;
case CV_16F:
return ACL_FLOAT16;
default:
return ACL_DT_UNDEFINED;
}
}
std::shared_ptr<uchar> mallocAndUpload(const void* data, size_t size, AscendStream& stream,
AscendMat::Allocator* allocator)
{
std::shared_ptr<uchar> ptr = allocator->allocate(size);
aclrtStream rawStream = AscendStreamAccessor::getStream(stream);
if (rawStream == nullptr)
CV_ACL_SAFE_CALL(aclrtMemcpy(ptr.get(), size, data, size, ACL_MEMCPY_HOST_TO_DEVICE));
else
CV_ACL_SAFE_CALL(
aclrtMemcpyAsync(ptr.get(), size, data, size, ACL_MEMCPY_HOST_TO_DEVICE, rawStream));
return ptr;
}
/**************************Acl attribute preparation**************************/
OperatorRunner& OperatorRunner::reset()
{
holder.clear();
op.clear();
for (auto desc : inputDesc_)
{
aclDestroyTensorDesc(desc);
}
for (auto desc : outputDesc_)
{
aclDestroyTensorDesc(desc);
}
for (auto buf : inputBuffers_)
{
CV_ACL_SAFE_CALL(aclDestroyDataBuffer(buf));
}
for (auto buf : outputBuffers_)
{
CV_ACL_SAFE_CALL(aclDestroyDataBuffer(buf));
}
if (opAttrInit)
aclopDestroyAttr(opAttr_);
inputDesc_.clear();
outputDesc_.clear();
inputBuffers_.clear();
outputBuffers_.clear();
opAttrInit = false;
return *this;
}
OperatorRunner& OperatorRunner::setOp(const char* opName)
{
reset();
opAttr_ = CV_ACL_SAFE_CALL_PTR(aclopCreateAttr());
opAttrInit = true;
op = std::string(opName);
return *this;
}
OperatorRunner& OperatorRunner::addAttr(float value, const char* name)
{
CV_ACL_SAFE_CALL(aclopSetAttrFloat(opAttr_, name, value));
return *this;
}
OperatorRunner& OperatorRunner::addAttr(const char* value, const char* name)
{
CV_ACL_SAFE_CALL(aclopSetAttrString(opAttr_, name, value));
return *this;
}
OperatorRunner& OperatorRunner::addAttr(int value, const char* name)
{
CV_ACL_SAFE_CALL(aclopSetAttrInt(opAttr_, name, value));
return *this;
}
OperatorRunner& OperatorRunner::addAttr(bool value, const char* name)
{
CV_ACL_SAFE_CALL(aclopSetAttrBool(opAttr_, name, value));
return *this;
}
OperatorRunner& OperatorRunner::addAttr(const int64_t* value, int size, const char* name)
{
CV_ACL_SAFE_CALL(aclopSetAttrListInt(opAttr_, name, size, value));
return *this;
}
OperatorRunner& OperatorRunner::addInput(AscendTensor& tensor)
{
auto descPtr = CV_ACL_SAFE_CALL_PTR(
aclCreateTensorDesc(tensor.dtype, tensor.dims.size(), &tensor.dims[0], tensor.format));
if (descPtr != nullptr)
{
if (tensor.name != nullptr && strlen(tensor.name) != 0)
aclSetTensorDescName(descPtr, tensor.name);
inputDesc_.push_back(descPtr);
}
auto bufPtr = CV_ACL_SAFE_CALL_PTR(aclCreateDataBuffer(tensor.data.get(), tensor.dataSize));
if (bufPtr != nullptr)
inputBuffers_.push_back(bufPtr);
holder.insert(tensor.data);
return *this;
}
OperatorRunner& OperatorRunner::addOutput(AscendTensor& tensor)
{
auto descPtr = CV_ACL_SAFE_CALL_PTR(
aclCreateTensorDesc(tensor.dtype, tensor.dims.size(), &tensor.dims[0], tensor.format));
if (descPtr != nullptr)
{
if (tensor.name != nullptr && strlen(tensor.name) != 0)
aclSetTensorDescName(descPtr, tensor.name);
outputDesc_.push_back(descPtr);
}
auto bufPtr = CV_ACL_SAFE_CALL_PTR(aclCreateDataBuffer(tensor.data.get(), tensor.dataSize));
if (bufPtr != nullptr)
outputBuffers_.push_back(bufPtr);
holder.insert(tensor.data);
return *this;
}
OperatorRunner& OperatorRunner::addInput(const AscendMat& mat, const char* name)
{
AscendTensor tensor(mat, name);
return addInput(tensor);
}
OperatorRunner& OperatorRunner::addOutput(AscendMat& mat, const char* name)
{
AscendTensor tensor(mat, name);
return addOutput(tensor);
}
OperatorRunner& OperatorRunner::addInput(const Scalar& sc, int type, const char* name)
{
uchar rawData[32];
cv::scalarToRawData(sc, rawData, type, 0);
std::shared_ptr<uchar> scPtr = mallocAndUpload(
rawData, (CV_ELEM_SIZE(type)), AscendStream::Null(), AscendMat::defaultAllocator());
int64_t dims[] = {1, 1, 1, (CV_MAT_CN(type))};
AscendTensor tensor(scPtr, (CV_ELEM_SIZE(type)), dims, sizeof(dims) / sizeof(dims[0]),
getACLType(CV_MAT_DEPTH(type)), name);
return addInput(tensor);
}
OperatorRunner& OperatorRunner::run(AscendStream& stream)
{
aclrtStream rawStream = AscendStreamAccessor::getStream(stream);
CV_ACL_SAFE_CALL(aclopCompileAndExecute(op.c_str(), inputDesc_.size(), inputDesc_.data(),
inputBuffers_.data(), outputDesc_.size(),
outputDesc_.data(), outputBuffers_.data(), opAttr_,
ACL_ENGINE_SYS, ACL_COMPILE_SYS, NULL, rawStream));
if (rawStream == nullptr)
CV_ACL_SAFE_CALL(aclrtSynchronizeStream(rawStream));
else
{
for (const auto& ptr : holder)
stream.addTensorHolder(ptr);
}
return *this;
}
/********************************Ascend Tensor********************************/
AscendTensor::AscendTensor(std::shared_ptr<uchar> _data, size_t _dataSize, int64_t* _dims,
size_t _dimSize, aclDataType _dtype, const char* _name,
aclFormat _format)
: name(_name), data(_data), dataSize(_dataSize), dtype(_dtype), format(_format)
{
dims.assign(_dims, _dims + _dimSize);
}
AscendTensor::AscendTensor(const AscendMat& ascendMat, const char* _name, aclFormat _format)
: name(_name), format(_format)
{
data = ascendMat.data;
// Ascend can't process with gaps in matrix.
CV_Assert(ascendMat.isContinuous());
dataSize = ascendMat.rows * ascendMat.cols * ascendMat.elemSize();
switch (_format)
{
case ACL_FORMAT_NHWC:
case ACL_FORMAT_ND:
dims.resize(4);
// Batch, default = 1.
dims[0] = 1;
// Default OpenCV image format = NHWC.
dims[1] = ascendMat.rows;
dims[2] = ascendMat.cols;
dims[3] = ascendMat.channels();
break;
case ACL_FORMAT_NCHW:
dims.resize(4);
dims[0] = 1;
dims[1] = ascendMat.channels();
dims[2] = ascendMat.rows;
dims[3] = ascendMat.cols;
break;
default:
CV_Error(Error::StsBadArg, "Unknown/unsupported matrix format");
}
dtype = getACLType(ascendMat.depth());
}
/**********************************Device*************************************/
void setDevice(int device_id)
{
aclrtContext context;
CV_ACL_SAFE_CALL(aclrtSetDevice(device_id));
CV_ACL_SAFE_CALL(aclrtCreateContext(&context, device_id));
}
void resetDevice() { CV_ACL_SAFE_CALL(aclrtResetDevice(getDevice())); }
int32_t getDevice()
{
int32_t deviceId;
CV_ACL_SAFE_CALL(aclrtGetDevice(&deviceId));
return deviceId;
}
void initAcl() { CV_ACL_SAFE_CALL(aclInit(nullptr)); }
void finalizeAcl() { CV_ACL_SAFE_CALL(aclFinalize()); }
class DefaultDeviceInitializer
{
public:
DefaultDeviceInitializer();
~DefaultDeviceInitializer();
AscendStream& getNullAscendStream(int deviceId);
private:
std::vector<Ptr<AscendStream>> streams_;
Mutex streams_mtx_;
};
DefaultDeviceInitializer::DefaultDeviceInitializer() {}
DefaultDeviceInitializer::~DefaultDeviceInitializer() { streams_.clear(); }
AscendStream& DefaultDeviceInitializer::getNullAscendStream(int deviceId)
{
AutoLock lock(streams_mtx_);
if (streams_.empty())
{
uint32_t deviceCount;
CV_ACL_SAFE_CALL(aclrtGetDeviceCount(&deviceCount));
if (deviceCount > 0)
streams_.resize(deviceCount);
}
CV_DbgAssert(deviceId >= 0 && deviceId < static_cast<int>(streams_.size()));
if (streams_[deviceId].empty())
{
aclrtStream stream = nullptr;
Ptr<AscendStream::Impl> impl = makePtr<AscendStream::Impl>(stream);
streams_[deviceId] = Ptr<AscendStream>(new AscendStream(impl));
}
return *streams_[deviceId];
}
DefaultDeviceInitializer initializer;
/***********************************Event*************************************/
AscendEvent::Impl::Impl() : event(nullptr), ownEvent(true)
{
CV_ACL_SAFE_CALL(aclrtCreateEvent(&event));
}
AscendEvent::Impl::Impl(aclrtEvent e) : event(e), ownEvent(false) {}
AscendEvent::Impl::~Impl()
{
if (event && ownEvent)
{
CV_ACL_SAFE_CALL(aclrtDestroyEvent(event));
}
}
aclrtEvent AscendEventAccessor::getEvent(const AscendEvent& event) { return event.impl_->event; }
AscendEvent AscendEventAccessor::wrapEvent(aclrtEvent event)
{
return AscendEvent(makePtr<AscendEvent::Impl>(event));
}
AscendEvent::AscendEvent() { impl_ = makePtr<Impl>(); }
void AscendEvent::record(AscendStream& stream)
{
CV_ACL_SAFE_CALL(aclrtRecordEvent(impl_->event, AscendStreamAccessor::getStream(stream)));
}
void AscendEvent::waitForComplete() const { CV_ACL_SAFE_CALL(aclrtSynchronizeEvent(impl_->event)); }
/************************************Stream***********************************/
void AscendStream::Impl::AddTensorHolder(const std::shared_ptr<uchar>& tensorData)
{
tensorHolders.insert(tensorData);
}
AscendStream::Impl::Impl() : stream(nullptr), ownStream(true)
{
CV_ACL_SAFE_CALL(aclrtCreateStream(&stream));
}
AscendStream::Impl::Impl(aclrtStream s) : stream(s), ownStream(false) {}
aclrtStream AscendStreamAccessor::getStream(const AscendStream& stream)
{
return stream.impl_->stream;
}
AscendStream AscendStreamAccessor::wrapStream(aclrtStream stream)
{
return AscendStream(makePtr<AscendStream::Impl>(stream));
}
AscendStream wrapStream(size_t AscendStreamAddress)
{
return AscendStreamAccessor::wrapStream(reinterpret_cast<aclrtStream>(AscendStreamAddress));
}
AscendStream::AscendStream() { impl_ = makePtr<Impl>(); }
void AscendStream::waitForCompletion()
{
CV_ACL_SAFE_CALL(aclrtSynchronizeStream(impl_->stream));
impl_->tensorHolders.clear();
}
void AscendStream::waitAscendEvent(const AscendEvent& event)
{
CV_ACL_SAFE_CALL(aclrtStreamWaitEvent(impl_->stream, AscendEventAccessor::getEvent(event)));
}
AscendStream& AscendStream::Null()
{
const uint32_t deviceId = getDevice();
return initializer.getNullAscendStream(deviceId);
}
void AscendStream::addTensorHolder(const std::shared_ptr<uchar>& holder)
{
impl_->AddTensorHolder(holder);
}
} // namespace cann
} // namespace cv
+777
View File
@@ -0,0 +1,777 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
namespace cv
{
namespace cann
{
// Integer type images will have a loss of accuracy during calculation, so they must be converted to
// float before calculation.
static AscendMat convertTo(const AscendMat& src, int dtype, AscendStream& stream)
{
AscendMat ret;
if (src.depth() != dtype)
src.convertTo(ret, dtype, stream);
else
ret = src;
return ret;
}
static void convertBack(const AscendMat& src, AscendMat& dst, AscendStream& stream)
{
if (src.depth() != dst.depth())
src.convertTo(dst, stream);
}
//! Set alpha channel to a Mat.
static void matAlphaSet(AscendMat& mat, int dtype, AscendStream& stream)
{
if (dtype < 0)
dtype = mat.depth();
if (mat.depth() == CV_8U || mat.depth() == CV_16U)
{
size_t size = mat.rows * mat.step;
aclrtMemsetWarpper(mat.data, 255, size, stream);
}
else
{
if (dtype == CV_32F)
mat.setTo(1.0f, stream);
else
mat.setTo((dtype == CV_8U ? (1 << 8) : (1 << 16)) - 1, stream);
}
}
inline void checkImg(const AscendMat& mat)
{
int depth = mat.depth();
CV_Assert(!mat.empty());
CV_Assert(depth == CV_8U || depth == CV_16U || depth == CV_32F);
}
inline void cvtBGRtoBGR(const AscendMat& src, AscendMat& dst, int dcn, bool swapBlue,
AscendStream& stream)
{
checkImg(src);
CV_Assert(src.channels() == 3 || src.channels() == 4);
AscendMat matChannels[4];
split(src, matChannels, stream);
if (swapBlue)
std::swap(matChannels[0], matChannels[2]);
if (dcn == 4 && src.channels() != 4)
{
AscendMat& alpha = matChannels[3];
alpha.create(src.rows, src.cols, CV_MAKE_TYPE(src.depth(), 1));
matAlphaSet(alpha, -1, stream);
}
merge(matChannels, dcn, dst, stream);
}
inline void cvtBGRtoBGR(InputArray& _src, OutputArray& _dst, int dcn, bool swapBlue,
AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
cvtBGRtoBGR(src, dst, dcn, swapBlue, stream);
dst.download(_dst, stream);
}
// TODO duplicated code
static const float B2YF = 0.114f;
static const float G2YF = 0.587f;
static const float R2YF = 0.299f;
inline void cvtBGRtoGray(const AscendMat& src, AscendMat& dst, int, bool swapBlue,
AscendStream& stream)
{
checkImg(src);
CV_Assert(src.channels() == 3 || src.channels() == 4);
float coeffs[] = {B2YF, G2YF, R2YF};
dst.create(src.rows, src.cols, CV_MAKE_TYPE(src.depth(), 1));
AscendMat formatedSrc = convertTo(src, CV_32F, stream);
AscendMat formatedDst = convertTo(dst, CV_32F, stream);
// For RGB
if (swapBlue)
std::swap(coeffs[0], coeffs[2]);
Scalar sc = {coeffs[0], coeffs[1], coeffs[2], 0};
AscendMat grayRet(formatedSrc.rows, formatedSrc.cols, formatedSrc.type());
arithm_op(formatedSrc, sc, grayRet, "Mul", stream);
AscendMat matChannels[4];
split(grayRet, matChannels, stream);
OperatorRunner runner;
runner.setOp("AddN")
.addInput(matChannels[0], "x0")
.addInput(matChannels[1], "x1")
.addInput(matChannels[2], "x2")
.addOutput(formatedDst, "y")
.addAttr(3, "N")
.run(stream);
convertBack(formatedDst, dst, stream);
}
inline void cvtBGRtoGray(const InputArray& _src, OutputArray& _dst, int, bool swapBlue,
AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
cvtBGRtoGray(src, dst, 0, swapBlue, stream);
dst.download(_dst, stream);
}
inline void cvtGraytoBGR(const AscendMat& src, AscendMat& dst, int dcn, bool, AscendStream& stream)
{
checkImg(src);
CV_Assert(src.channels() == 1);
AscendMat matChannels[4];
for (int i = 0; i < 3; i++)
matChannels[i] = src;
if (dcn == 4)
{
AscendMat& alpha = matChannels[3];
alpha.create(src.rows, src.cols, CV_MAKE_TYPE(src.depth(), 1));
matAlphaSet(alpha, -1, stream);
}
merge(matChannels, dcn, dst, stream);
}
inline void cvtGraytoBGR(const InputArray& _src, OutputArray& _dst, int dcn, bool,
AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
cvtGraytoBGR(src, dst, dcn, false, stream);
dst.download(_dst, stream);
}
static const float RGB2XYZ_D65[] = {0.412453, 0.357580, 0.180423, 0.212671, 0.715160,
0.072169, 0.019334, 0.119193, 0.950227};
static const float XYZ2RGB_D65[] = {3.240479, -1.53715, -0.498535, -0.969256, 1.875991,
0.041556, 0.055648, -0.204043, 1.057311};
inline void matMulRGB(const AscendMat& src, AscendMat& dst, float* matrix, AscendStream& stream)
{
checkImg(src);
CV_Assert(src.channels() == 3);
dst.create(src.rows, src.cols, src.type());
AscendMat formatedSrc = convertTo(src, CV_32F, stream);
AscendMat formatedDst = convertTo(dst, CV_32F, stream);
int64_t dims[] = {3, 3};
OperatorRunner runner;
runner.setOp("BatchMatMulV2")
.addInput(formatedSrc, "x1")
.addInput<float>(matrix, dims, 2, getACLType(CV_32F), "x2")
.addOutput(formatedDst, "y")
.addAttr(false, "adj_x1")
.addAttr(true, "adj_x2")
.run(stream);
if (src.depth() != CV_32F)
{
AscendMat thresholdTempMat(formatedSrc.size(), formatedSrc.type());
uint16_t thresh = (src.depth() == CV_8U ? (1 << 8) : (1 << 16)) - 1;
threshold(formatedDst, thresholdTempMat, thresh, 0, 2 /*THRESH_TRUNC*/, stream);
threshold(thresholdTempMat, formatedDst, 0, 0, 3 /*THRESH_TOZERO*/, stream);
}
convertBack(formatedDst, dst, stream);
}
// TODO: should deal with overflow. set 255 instead of cut off.
inline void cvtBGRtoXYZ(const AscendMat& src, AscendMat& dst, int, bool swapBlue,
AscendStream& stream)
{
float coeffs[9];
memcpy(coeffs, RGB2XYZ_D65, 9 * sizeof(float));
if (!swapBlue)
{
std::swap(coeffs[0], coeffs[2]);
std::swap(coeffs[3], coeffs[5]);
std::swap(coeffs[6], coeffs[8]);
}
matMulRGB(src, dst, coeffs, stream);
}
inline void cvtBGRtoXYZ(const InputArray& _src, OutputArray& _dst, int, bool swapBlue,
AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
cvtBGRtoXYZ(src, dst, 0, swapBlue, stream);
dst.download(_dst, stream);
}
inline void cvtXYZtoBGR(const AscendMat& src, AscendMat& dst, int dcn, bool swapBlue,
AscendStream& stream)
{
float coeffs[9];
memcpy(coeffs, XYZ2RGB_D65, 9 * sizeof(float));
if (!swapBlue)
{
std::swap(coeffs[0], coeffs[6]);
std::swap(coeffs[1], coeffs[7]);
std::swap(coeffs[2], coeffs[8]);
}
if (dcn == 4)
{
AscendMat tempMat[2];
matMulRGB(src, tempMat[0], coeffs, stream);
tempMat[1].create(tempMat[0].rows, tempMat[0].cols, CV_MAKE_TYPE(tempMat[0].depth(), 1));
matAlphaSet(tempMat[1], -1, stream);
merge(tempMat, 2, dst, stream);
}
else
matMulRGB(src, dst, coeffs, stream);
}
inline void cvtXYZtoBGR(const InputArray& _src, OutputArray& _dst, int dcn, bool swapBlue,
AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
cvtXYZtoBGR(src, dst, dcn, swapBlue, stream);
dst.download(_dst, stream);
}
// TODO duplicated code
static const float YCRF = 0.713f;
static const float YCBF = 0.564f;
static const float R2VF = 0.877f;
static const float B2UF = 0.492f;
inline void cvtBGRtoYCrCb(const AscendMat& src, AscendMat& dst, float* coeffs, bool swapBlue,
bool yuvOrder, AscendStream& stream)
{
checkImg(src);
CV_Assert(src.channels() == 3);
int buleIdx = swapBlue ? 2 : 0;
int depth = src.depth();
float delta = (depth == CV_8U) ? 128 : ((depth == CV_16U) ? 32768 : 0.5);
dst.create(src.rows, src.cols, src.type());
AscendMat formatedSrc = convertTo(src, CV_32F, stream);
AscendMat formatedDst = convertTo(dst, CV_32F, stream);
AscendMat YCrCb[3], RGB[3];
split(formatedSrc, RGB, stream);
cvtBGRtoGray(formatedSrc, YCrCb[0], 1, swapBlue, stream);
YCrCb[1].create(YCrCb[0].rows, YCrCb[0].cols, YCrCb[0].type());
YCrCb[2].create(YCrCb[0].rows, YCrCb[0].cols, YCrCb[0].type());
AscendMat tempMat1(formatedSrc.size(), CV_MAKE_TYPE(formatedSrc.depth(), 1)),
tempMat2(formatedSrc.size(), CV_MAKE_TYPE(formatedSrc.depth(), 1));
arithm_op(RGB[buleIdx ^ 2], YCrCb[0], tempMat1, "Sub", stream);
arithm_op(tempMat1, coeffs[0], tempMat2, "Muls", stream);
arithm_op(tempMat2, delta, YCrCb[1], "Adds", stream);
arithm_op(RGB[buleIdx], YCrCb[0], tempMat1, "Sub", stream);
arithm_op(tempMat1, coeffs[1], tempMat2, "Muls", stream);
arithm_op(tempMat2, delta, YCrCb[2], "Adds", stream);
if (yuvOrder)
std::swap(YCrCb[1], YCrCb[2]);
merge(YCrCb, 3, formatedDst, stream);
if (src.depth() != CV_32F)
{
AscendMat thresholdTempMat(formatedSrc.size(), formatedSrc.type());
uint16_t thresh = (src.depth() == CV_8U ? (1 << 8) : (1 << 16)) - 1;
threshold(formatedDst, thresholdTempMat, thresh, 0, 2 /*THRESH_TRUNC*/, stream);
threshold(thresholdTempMat, formatedDst, 0, 0, 3 /*THRESH_TOZERO*/, stream);
}
convertBack(formatedDst, dst, stream);
}
inline void cvtBGRtoYCrCb(const InputArray& _src, OutputArray& _dst, float* coeffs, bool swapBlue,
bool yuvOrder, AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
cvtBGRtoYCrCb(src, dst, coeffs, swapBlue, yuvOrder, stream);
dst.download(_dst, stream);
}
static const float CR2RF = 1.403f;
static const float CR2GF = -0.714f;
static const float CB2GF = -0.344f;
static const float CB2BF = 1.773f;
static const float V2RF = 1.140f;
static const float V2GF = -0.581f;
static const float U2GF = -0.395f;
static const float U2BF = 2.032f;
inline void cvtYCrCbtoBGR(const AscendMat& src, AscendMat& dst, int dcn, float* coeffs,
bool swapBlue, bool yuvOrder, AscendStream& stream)
{
checkImg(src);
CV_Assert(src.channels() == 3);
int buleIdx = swapBlue ? 2 : 0;
int depth = src.depth();
float delta = (depth == CV_8U) ? 128 : ((depth == CV_16U) ? 32768 : 0.5);
dst.create(src.rows, src.cols, CV_MAKE_TYPE(src.depth(), dcn));
AscendMat formatedSrc = convertTo(src, CV_32F, stream);
AscendMat formatedDst = convertTo(dst, CV_32F, stream);
AscendMat YCrCb[3], RGB[4];
split(formatedSrc, YCrCb, stream);
if (yuvOrder)
std::swap(YCrCb[1], YCrCb[2]);
RGB[0].create(formatedSrc.rows, formatedSrc.cols, CV_MAKE_TYPE(formatedSrc.depth(), 1));
RGB[1].create(formatedSrc.rows, formatedSrc.cols, CV_MAKE_TYPE(formatedSrc.depth(), 1));
RGB[2].create(formatedSrc.rows, formatedSrc.cols, CV_MAKE_TYPE(formatedSrc.depth(), 1));
AscendMat tempMat1(formatedSrc.size(), CV_MAKE_TYPE(formatedSrc.depth(), 1)),
tempMat2(formatedSrc.size(), CV_MAKE_TYPE(formatedSrc.depth(), 1)),
CbSubDelta(formatedSrc.size(), CV_MAKE_TYPE(formatedSrc.depth(), 1)),
CrSubDelta(formatedSrc.size(), CV_MAKE_TYPE(formatedSrc.depth(), 1));
arithm_op(YCrCb[1], (0.0f - delta), CrSubDelta, "Adds", stream);
arithm_op(YCrCb[2], (0.0f - delta), CbSubDelta, "Adds", stream);
arithm_op(CrSubDelta, coeffs[0], tempMat1, "Muls", stream);
arithm_op(YCrCb[0], tempMat1, RGB[buleIdx ^ 2], "Add", stream);
arithm_op(CrSubDelta, coeffs[1], tempMat1, "Muls", stream);
arithm_op(YCrCb[0], tempMat1, tempMat2, "Add", stream);
arithm_op(CbSubDelta, coeffs[2], tempMat1, "Muls", stream);
arithm_op(tempMat2, tempMat1, RGB[1], "Add", stream);
arithm_op(CbSubDelta, coeffs[3], tempMat1, "Muls", stream);
arithm_op(YCrCb[0], tempMat1, RGB[buleIdx], "Add", stream);
if (dcn == 4)
{
RGB[3].create(RGB[0].rows, RGB[0].cols, RGB[0].type());
matAlphaSet(RGB[3], src.depth(), stream);
}
merge(RGB, dcn, formatedDst, stream);
if (src.depth() != CV_32F)
{
AscendMat thresholdTempMat(formatedSrc.size(), CV_MAKE_TYPE(formatedSrc.depth(), dcn));
uint16_t thresh = (src.depth() == CV_8U ? (1 << 8) : (1 << 16)) - 1;
threshold(formatedDst, thresholdTempMat, thresh, 0, 2 /*THRESH_TRUNC*/, stream);
threshold(thresholdTempMat, formatedDst, 0, 0, 3 /*THRESH_TOZERO*/, stream);
}
convertBack(formatedDst, dst, stream);
}
inline void cvtYCrCbtoBGR(const InputArray& _src, OutputArray& _dst, int dcn, float* coeffs,
bool swapBlue, bool yuvOrder, AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
cvtYCrCbtoBGR(src, dst, dcn, coeffs, swapBlue, yuvOrder, stream);
dst.download(_dst, stream);
}
// The input may be Input/OutputArray or AscendMat. Use templates to reduce duplicate code.
template <typename SRC, typename DST>
inline void BGR2BGRA(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoBGR(src, dst, 4, false, stream);
}
template <typename SRC, typename DST>
inline void BGRA2BGR(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoBGR(src, dst, 3, false, stream);
}
template <typename SRC, typename DST>
inline void BGR2RGBA(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoBGR(src, dst, 4, true, stream);
}
template <typename SRC, typename DST>
inline void RGBA2BGR(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoBGR(src, dst, 3, true, stream);
}
template <typename SRC, typename DST>
inline void BGR2RGB(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoBGR(src, dst, 3, true, stream);
}
template <typename SRC, typename DST>
inline void BGRA2RGBA(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoBGR(src, dst, 4, true, stream);
}
template <typename SRC, typename DST>
inline void BGR2GRAY(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoGray(src, dst, 1, false, stream);
}
template <typename SRC, typename DST>
inline void RGB2GRAY(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoGray(src, dst, 1, true, stream);
}
template <typename SRC, typename DST>
inline void GRAY2BGR(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtGraytoBGR(src, dst, 3, false, stream);
}
template <typename SRC, typename DST>
inline void GRAY2BGRA(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtGraytoBGR(src, dst, 4, false, stream);
}
template <typename SRC, typename DST>
inline void BGRA2GRAY(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoGray(src, dst, 1, false, stream);
}
template <typename SRC, typename DST>
inline void RGBA2GRAY(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoGray(src, dst, 1, true, stream);
}
template <typename SRC, typename DST>
inline void BGR2XYZ(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoXYZ(src, dst, 3, false, stream);
}
template <typename SRC, typename DST>
inline void RGB2XYZ(const SRC& src, DST& dst, int, AscendStream& stream)
{
cvtBGRtoXYZ(src, dst, 3, true, stream);
}
template <typename SRC, typename DST>
inline void XYZ2BGR(const SRC& src, DST& dst, int dcn, AscendStream& stream)
{
if (dcn <= 0)
dcn = 3;
cvtXYZtoBGR(src, dst, dcn, false, stream);
}
template <typename SRC, typename DST>
inline void XYZ2RGB(const SRC& src, DST& dst, int dcn, AscendStream& stream)
{
if (dcn <= 0)
dcn = 3;
cvtXYZtoBGR(src, dst, dcn, true, stream);
}
template <typename SRC, typename DST>
inline void BGR2YCrCb(const SRC& src, DST& dst, int, AscendStream& stream)
{
float coeffs[2];
coeffs[0] = YCRF;
coeffs[1] = YCBF;
cvtBGRtoYCrCb(src, dst, coeffs, false, false, stream);
}
template <typename SRC, typename DST>
inline void RGB2YCrCb(const SRC& src, DST& dst, int, AscendStream& stream)
{
float coeffs[2];
coeffs[0] = YCRF;
coeffs[1] = YCBF;
cvtBGRtoYCrCb(src, dst, coeffs, true, false, stream);
}
template <typename SRC, typename DST>
inline void YCrCb2BGR(const SRC& src, DST& dst, int dcn, AscendStream& stream)
{
float coeffs[4];
coeffs[0] = CR2RF;
coeffs[1] = CR2GF;
coeffs[2] = CB2GF;
coeffs[3] = CB2BF;
if (dcn <= 0)
dcn = 3;
cvtYCrCbtoBGR(src, dst, dcn, coeffs, false, false, stream);
}
template <typename SRC, typename DST>
inline void YCrCb2RGB(const SRC& src, DST& dst, int dcn, AscendStream& stream)
{
float coeffs[4];
coeffs[0] = CR2RF;
coeffs[1] = CR2GF;
coeffs[2] = CB2GF;
coeffs[3] = CB2BF;
if (dcn <= 0)
dcn = 3;
cvtYCrCbtoBGR(src, dst, dcn, coeffs, true, false, stream);
}
template <typename SRC, typename DST>
inline void BGR2YUV(const SRC& src, DST& dst, int, AscendStream& stream)
{
float coeffs[2];
coeffs[0] = R2VF;
coeffs[1] = B2UF;
cvtBGRtoYCrCb(src, dst, coeffs, false, true, stream);
}
template <typename SRC, typename DST>
inline void RGB2YUV(const SRC& src, DST& dst, int, AscendStream& stream)
{
float coeffs[2];
coeffs[0] = R2VF;
coeffs[1] = B2UF;
cvtBGRtoYCrCb(src, dst, coeffs, true, true, stream);
}
template <typename SRC, typename DST>
inline void YUV2BGR(const SRC& src, DST& dst, int dcn, AscendStream& stream)
{
float coeffs[4];
coeffs[0] = V2RF;
coeffs[1] = V2GF;
coeffs[2] = U2GF;
coeffs[3] = U2BF;
if (dcn <= 0)
dcn = 3;
cvtYCrCbtoBGR(src, dst, dcn, coeffs, false, true, stream);
}
template <typename SRC, typename DST>
inline void YUV2RGB(const SRC& src, DST& dst, int dcn, AscendStream& stream)
{
float coeffs[4];
coeffs[0] = V2RF;
coeffs[1] = V2GF;
coeffs[2] = U2GF;
coeffs[3] = U2BF;
if (dcn <= 0)
dcn = 3;
cvtYCrCbtoBGR(src, dst, dcn, coeffs, true, true, stream);
}
template <typename SRC, typename DST>
void cvtColorDo(const SRC& src, DST& dst, int code, int dcn, AscendStream& stream)
{
typedef void (*func_t)(const SRC& src, DST& dst, int dcn, AscendStream& stream);
static const func_t funcs[] = {
BGR2BGRA, // CV_BGR2BGRA =0
BGRA2BGR, // CV_BGRA2BGR =1
BGR2RGBA, // CV_BGR2RGBA =2
RGBA2BGR, // CV_RGBA2BGR =3
BGR2RGB, // CV_BGR2RGB =4
BGRA2RGBA, // CV_BGRA2RGBA =5
BGR2GRAY, // CV_BGR2GRAY =6
RGB2GRAY, // CV_RGB2GRAY =7
GRAY2BGR, // CV_GRAY2BGR =8
GRAY2BGRA, // CV_GRAY2BGRA =9
BGRA2GRAY, // CV_BGRA2GRAY =10
RGBA2GRAY, // CV_RGBA2GRAY =11
0, // CV_BGR2BGR565 =12
0, // CV_RGB2BGR565 =13
0, // CV_BGR5652BGR =14
0, // CV_BGR5652RGB =15
0, // CV_BGRA2BGR565 =16
0, // CV_RGBA2BGR565 =17
0, // CV_BGR5652BGRA =18
0, // CV_BGR5652RGBA =19
0, // CV_GRAY2BGR565 =20
0, // CV_BGR5652GRAY =21
0, // CV_BGR2BGR555 =22
0, // CV_RGB2BGR555 =23
0, // CV_BGR5552BGR =24
0, // CV_BGR5552RGB =25
0, // CV_BGRA2BGR555 =26
0, // CV_RGBA2BGR555 =27
0, // CV_BGR5552BGRA =28
0, // CV_BGR5552RGBA =29
0, // CV_GRAY2BGR555 =30
0, // CV_BGR5552GRAY =31
BGR2XYZ, // CV_BGR2XYZ =32
RGB2XYZ, // CV_RGB2XYZ =33
XYZ2BGR, // CV_XYZ2BGR =34
XYZ2RGB, // CV_XYZ2RGB =35
BGR2YCrCb, // CV_BGR2YCrCb =36
RGB2YCrCb, // CV_RGB2YCrCb =37
YCrCb2BGR, // CV_YCrCb2BGR =38
YCrCb2RGB, // CV_YCrCb2RGB =39
0, // CV_BGR2HSV =40
0, // CV_RGB2HSV =41
0, // =42
0, // =43
0, // CV_BGR2Lab =44
0, // CV_RGB2Lab =45
0, // CV_BayerBG2BGR =46
0, // CV_BayeRGB2BGR =47
0, // CV_BayerRG2BGR =48
0, // CV_BayerGR2BGR =49
0, // CV_BGR2Luv =50
0, // CV_RGB2Luv =51
0, // CV_BGR2HLS =52
0, // CV_RGB2HLS =53
0, // CV_HSV2BGR =54
0, // CV_HSV2RGB =55
0, // CV_Lab2BGR =56
0, // CV_Lab2RGB =57
0, // CV_Luv2BGR =58
0, // CV_Luv2RGB =59
0, // CV_HLS2BGR =60
0, // CV_HLS2RGB =61
0, // CV_BayerBG2BGR_VNG =62
0, // CV_BayeRGB2BGR_VNG =63
0, // CV_BayerRG2BGR_VNG =64
0, // CV_BayerGR2BGR_VNG =65
0, // CV_BGR2HSV_FULL = 66
0, // CV_RGB2HSV_FULL = 67
0, // CV_BGR2HLS_FULL = 68
0, // CV_RGB2HLS_FULL = 69
0, // CV_HSV2BGR_FULL = 70
0, // CV_HSV2RGB_FULL = 71
0, // CV_HLS2BGR_FULL = 72
0, // CV_HLS2RGB_FULL = 73
0, // CV_LBGR2Lab = 74
0, // CV_LRGB2Lab = 75
0, // CV_LBGR2Luv = 76
0, // CV_LRGB2Luv = 77
0, // CV_Lab2LBGR = 78
0, // CV_Lab2LRGB = 79
0, // CV_Luv2LBGR = 80
0, // CV_Luv2LRGB = 81
BGR2YUV, // CV_BGR2YUV = 82
RGB2YUV, // CV_RGB2YUV = 83
YUV2BGR, // CV_YUV2BGR = 84
YUV2RGB, // CV_YUV2RGB = 85
0, // CV_BayerBG2GRAY = 86
0, // CV_BayeRGB2GRAY = 87
0, // CV_BayerRG2GRAY = 88
0, // CV_BayerGR2GRAY = 89
// YUV 4:2:0 formats family
0, // CV_YUV2RGB_NV12 = 90,
0, // CV_YUV2BGR_NV12 = 91,
0, // CV_YUV2RGB_NV21 = 92,
0, // CV_YUV2BGR_NV21 = 93,
0, // CV_YUV2RGBA_NV12 = 94,
0, // CV_YUV2BGRA_NV12 = 95,
0, // CV_YUV2RGBA_NV21 = 96,
0, // CV_YUV2BGRA_NV21 = 97,
0, // CV_YUV2RGB_YV12 = 98,
0, // CV_YUV2BGR_YV12 = 99,
0, // CV_YUV2RGB_IYUV = 100,
0, // CV_YUV2BGR_IYUV = 101,
0, // CV_YUV2RGBA_YV12 = 102,
0, // CV_YUV2BGRA_YV12 = 103,
0, // CV_YUV2RGBA_IYUV = 104,
0, // CV_YUV2BGRA_IYUV = 105,
0, // CV_YUV2GRAY_420 = 106,
// YUV 4:2:2 formats family
0, // CV_YUV2RGB_UYVY = 107,
0, // CV_YUV2BGR_UYVY = 108,
0, // //CV_YUV2RGB_VYUY = 109,
0, // //CV_YUV2BGR_VYUY = 110,
0, // CV_YUV2RGBA_UYVY = 111,
0, // CV_YUV2BGRA_UYVY = 112,
0, // //CV_YUV2RGBA_VYUY = 113,
0, // //CV_YUV2BGRA_VYUY = 114,
0, // CV_YUV2RGB_YUY2 = 115,
0, // CV_YUV2BGR_YUY2 = 116,
0, // CV_YUV2RGB_YVYU = 117,
0, // CV_YUV2BGR_YVYU = 118,
0, // CV_YUV2RGBA_YUY2 = 119,
0, // CV_YUV2BGRA_YUY2 = 120,
0, // CV_YUV2RGBA_YVYU = 121,
0, // CV_YUV2BGRA_YVYU = 122,
0, // CV_YUV2GRAY_UYVY = 123,
0, // CV_YUV2GRAY_YUY2 = 124,
// alpha premultiplication
0, // CV_RGBA2mRGBA = 125,
0, // CV_mRGBA2RGBA = 126,
0, // CV_COLORCVT_MAX = 127
};
CV_Assert(code < 128);
func_t func = funcs[code];
if (func == 0)
CV_Error(Error::StsBadFlag, "Unknown/unsupported color conversion code");
func(src, dst, dcn, stream);
}
// Instantiate templates to avoid confusion in python code generation
void cvtColor(const InputArray src, OutputArray dst, int code, int dcn, AscendStream& stream)
{
cvtColorDo(src, dst, code, dcn, stream);
}
void cvtColor(const AscendMat& src, AscendMat& dst, int code, int dcn, AscendStream& stream)
{
cvtColorDo(src, dst, code, dcn, stream);
}
} // namespace cann
} // namespace cv
+477
View File
@@ -0,0 +1,477 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
namespace cv
{
namespace cann
{
// Transform data type from one to another. eg. from NCHW to NHWC.
void transData(const AscendMat& src, AscendMat& dst, const char* from, const char* to,
AscendStream& stream)
{
OperatorRunner runner;
runner.setOp("TransData")
.addInput(src, "src")
.addOutput(dst, "dst")
.addAttr(from, "src_format")
.addAttr(to, "dst_format")
.run(stream);
}
void merge(const AscendMat* src, size_t n, AscendMat& dst, AscendStream& stream)
{
if (src == nullptr || n < 2)
return;
int depth = src->depth();
int rows = src->rows;
int cols = src->cols;
// All matrix must have same size and type
for (size_t i = 1; i < n; i++)
{
CV_Assert(src[i].depth() == depth && src[i].channels() == 1);
CV_Assert(src[i].rows == rows && src[i].cols == cols);
}
int cns = 0;
for (size_t i = 0; i < n; i++)
cns += src[i].channels();
dst.create(src->rows, src->cols, CV_MAKE_TYPE(src->depth(), cns));
OperatorRunner runner;
runner.setOp("ConcatD");
for (size_t i = 0; i < n; i++)
{
runner.addInput(src[i], ("x" + std::to_string(i)).c_str());
}
runner.addOutput(dst, "output_data").addAttr(3, "concat_dim").run(stream);
}
void merge(const std::vector<AscendMat>& src, AscendMat& dst, AscendStream& stream)
{
merge(&src[0], src.size(), dst, stream);
}
void merge(const AscendMat* src, size_t n, OutputArray& _dst, AscendStream& stream)
{
AscendMat dst;
merge(src, n, dst, stream);
dst.download(_dst, stream);
}
void merge(const std::vector<AscendMat>& src, OutputArray& dst, AscendStream& stream)
{
merge(&src[0], src.size(), dst, stream);
}
void split(const AscendMat& src, AscendMat* dst, AscendStream& stream)
{
if (src.empty() || dst == nullptr)
return;
int cn = src.channels();
OperatorRunner runner;
runner.setOp("SplitD").addInput(src, "x");
for (int i = 0; i < cn; i++)
{
dst[i].create(src.rows, src.cols, CV_MAKE_TYPE(src.depth(), 1));
runner.addOutput(dst[i], ("y" + std::to_string(i)).c_str());
}
runner.addAttr(3, "split_dim").addAttr(cn, "num_split").run(stream);
}
void split(const AscendMat& src, std::vector<AscendMat>& dst, AscendStream& stream)
{
dst.resize(src.channels());
split(src, &dst[0], stream);
}
void split(const InputArray _src, AscendMat* dst, AscendStream& stream)
{
AscendMat src;
src.upload(_src, stream);
split(src, dst, stream);
}
void split(const InputArray _src, std::vector<AscendMat>& dst, AscendStream& stream)
{
AscendMat src;
src.upload(_src, stream);
dst.resize(src.channels());
split(_src, &dst[0], stream);
}
void transpose(const AscendMat& src, int64_t* perm, AscendMat& dst, AscendStream& stream)
{
OperatorRunner runner;
runner.setOp("TransposeD")
.addInput(src, "x")
.addOutput(dst, "y")
.addAttr(perm, 4, "perm")
.run(stream);
}
void transpose(const AscendMat& src, AscendMat& dst, AscendStream& stream)
{
int64_t perm[] = {0, 2, 1, 3};
dst.create(src.cols, src.rows, src.type());
transpose(src, perm, dst, stream);
}
void transpose(InputArray _src, OutputArray _dst, AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
transpose(src, dst, stream);
dst.download(_dst, stream);
}
void flip(const AscendMat& src, std::vector<int32_t>& asixs, AscendMat& dst, AscendStream& stream)
{
int64_t dim = asixs.size();
OperatorRunner runner;
runner.setOp("ReverseV2")
.addInput(src, "x")
.addInput<int32_t>(&asixs.at(0), &dim, 1, ACL_INT32, "axis")
.addOutput(dst, "y")
.run(stream);
}
void flip(const AscendMat& src, AscendMat& dst, int flipCode, AscendStream& stream)
{
std::vector<int32_t> asix;
if (flipCode == 0)
asix.push_back(1);
else if (flipCode > 0)
asix.push_back(2);
else
{
asix.push_back(1);
asix.push_back(2);
}
dst.create(src.rows, src.cols, src.type());
flip(src, asix, dst, stream);
}
void flip(const InputArray _src, OutputArray _dst, int flipCode, AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
flip(src, dst, flipCode, stream);
dst.download(_dst, stream);
}
void rotate(const AscendMat& src, AscendMat& dst, int rotateMode, AscendStream& stream)
{
AscendMat tempMat;
switch (rotateMode)
{
case ROTATE_90_CLOCKWISE:
{
dst.create(src.cols, src.rows, src.type());
transpose(src, tempMat, stream);
flip(tempMat, dst, 1, stream);
break;
}
case ROTATE_180:
{
dst.create(src.rows, src.cols, src.type());
flip(src, dst, -1, stream);
break;
}
case ROTATE_90_COUNTERCLOCKWISE:
{
dst.create(src.cols, src.rows, src.type());
transpose(src, tempMat, stream);
flip(tempMat, dst, 0, stream);
break;
}
default:
break;
}
}
void rotate(InputArray _src, OutputArray _dst, int rotateMode, AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
rotate(src, dst, rotateMode, stream);
dst.download(_dst, stream);
}
void crop(const AscendMat& src, AscendMat& dst, const AscendMat& sizeSrcNpu, int64_t* offset,
AscendStream& stream)
{
OperatorRunner runner;
runner.setOp("Crop")
.addInput(src, "x")
.addInput(sizeSrcNpu, "size")
.addAttr(1, "axis")
.addAttr(offset, 3, "offsets")
.addOutput(dst, "y")
.run(stream);
}
AscendMat crop(const AscendMat& src, const Rect& rect, AscendStream& stream)
{
AscendMat dst, sizeSrcNpu;
// left-up conner
int x = rect.x, y = rect.y, width = rect.width, height = rect.height;
int64_t offset[] = {y, x, 0};
CV_Assert(x + width <= src.cols && y + height <= src.rows);
int size1[] = {1, src.channels(), height, width};
dst.create(height, width, src.type());
Mat sizeSrc(height, width, src.type(), size1);
sizeSrcNpu.upload(sizeSrc);
crop(src, dst, sizeSrcNpu, offset, stream);
return dst;
}
AscendMat crop(InputArray _src, const Rect& rect, AscendStream& stream)
{
AscendMat src;
src.upload(_src, stream);
return crop(src, rect, stream);
}
/************************** resize **************************/
void checkResize(Size& ssize, Size& dsize, double inv_scale_x, double inv_scale_y,
int& interpolation)
{
CV_Assert(!ssize.empty());
float_t scaleX = (float_t)inv_scale_x;
float_t scaleY = (float_t)inv_scale_y;
// interpolation: resize mode, support bilinear/nearest neighbor/bicubic/pixel area relation.
CV_Assert(interpolation == INTER_LINEAR || interpolation == INTER_NEAREST ||
interpolation == INTER_CUBIC || interpolation == INTER_AREA);
switch (interpolation)
{
case INTER_LINEAR:
interpolation = INTER_NEAREST;
break;
case INTER_NEAREST:
interpolation = INTER_LINEAR;
break;
default:
break;
}
if (dsize.empty())
{
CV_Assert(scaleX > 0);
CV_Assert(scaleY > 0);
dsize = Size(saturate_cast<int>(ssize.width * inv_scale_x),
saturate_cast<int>(ssize.height * inv_scale_y));
CV_Assert(!dsize.empty());
}
else
{
scaleX = (float_t)dsize.width / ssize.width;
scaleY = (float_t)dsize.height / ssize.height;
CV_Assert(scaleX > 0);
CV_Assert(scaleY > 0);
}
}
template <typename inMat, typename outMat>
void resize(const inMat& src, outMat& dst, int interpolation)
{
DvppOperatorDesc op;
op.addInput(src).addOutput(dst);
uint32_t taskID = 0;
vpcResizeWarpper(op.chnId, op.inputDesc_[0].Pic, op.outputDesc_[0].Pic, interpolation, &taskID);
uint32_t taskIDResult = taskID;
op.getResult(dst, taskIDResult);
}
void resize(const AscendMat& src, AscendMat& dst, int32_t* dstSize, int interpolation,
AscendStream& stream)
{
OperatorRunner runner;
int64_t dims[] = {2};
char const* mode = "";
switch (interpolation)
{
case INTER_CUBIC:
mode = "ResizeBicubic";
break;
case INTER_AREA:
mode = "ResizeArea";
break;
default:
break;
}
runner.setOp(mode)
.addInput(src, "images")
.addInput<int32_t>(dstSize, dims, 1, ACL_INT32, "size")
.addAttr(true, "half_pixel_centers")
.addOutput(dst, "y")
.run(stream);
}
void resize(const AscendMat& src, AscendMat& dst, Size dsize, double inv_scale_x,
double inv_scale_y, int interpolation, AscendStream& stream)
{
Size ssize = src.size();
checkResize(ssize, dsize, inv_scale_x, inv_scale_y, interpolation);
int32_t dstSize[] = {dsize.height, dsize.width};
dst.create(dstSize[0], dstSize[1], src.type());
if (interpolation == INTER_CUBIC || interpolation == INTER_AREA)
{
resize(src, dst, dstSize, interpolation, stream);
}
else
{
resize(src, dst, interpolation);
}
}
void resize(InputArray _src, OutputArray _dst, Size dsize, double inv_scale_x, double inv_scale_y,
int interpolation, AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
if (interpolation == INTER_CUBIC || interpolation == INTER_AREA)
{
resize(src, dst, dsize, inv_scale_x, inv_scale_y, interpolation, stream);
dst.download(_dst, stream);
}
else
{
Mat srcCV = _src.getMat();
Size ssize = srcCV.size();
checkResize(ssize, dsize, inv_scale_x, inv_scale_y, interpolation);
_dst.create(dsize, srcCV.type());
Mat dstCV = _dst.getMat();
resize(srcCV, dstCV, interpolation);
}
}
/************************** CropResize **************************/
template <typename inMat, typename outMat>
void cropResize(const inMat& src, outMat& dst, const Rect& rect, Size dsize, int interpolation)
{
DvppOperatorDesc op;
op.addInput(src).addOutput(dst);
uint32_t taskID = 0;
int cnt = 1;
vpcCropResizeWarpper(op.chnId, op.inputDesc_[0].Pic, op.outputDesc_[0].Pic, cnt, &taskID, rect,
dsize, interpolation);
uint32_t taskIDResult = taskID;
op.getResult(dst, taskIDResult);
}
void cropResize(const AscendMat& src, AscendMat& dst, const Rect& rect, Size dsize,
double inv_scale_x, double inv_scale_y, int interpolation)
{
Size ssize = src.size();
checkResize(ssize, dsize, inv_scale_x, inv_scale_y, interpolation);
dst.create(dsize.height, dsize.width, src.type());
cropResize(src, dst, rect, dsize, interpolation);
}
void cropResize(const InputArray _src, OutputArray _dst, const Rect& rect, Size dsize,
double inv_scale_x, double inv_scale_y, int interpolation)
{
Size ssize = _src.size();
checkResize(ssize, dsize, inv_scale_x, inv_scale_y, interpolation);
Mat src = _src.getMat();
_dst.create(dsize.height, dsize.width, src.type());
Mat dst = _dst.getMat();
cropResize(src, dst, rect, dsize, interpolation);
}
/************************** CopyMakeBorder **************************/
template <typename inMat, typename outMat>
void copyMakeBorder(const inMat& src, outMat& dst, int* offsets, int borderType,
const Scalar& value)
{
DvppOperatorDesc op;
op.addInput(src).addOutput(dst);
uint32_t taskID = 0;
vpcCopyMakeBorderWarpper(op.chnId, op.inputDesc_[0].Pic, op.outputDesc_[0].Pic, &taskID,
offsets, borderType, value);
uint32_t taskIDResult = taskID;
op.getResult(dst, taskIDResult);
}
void copyMakeBorder(const AscendMat& src, AscendMat& dst, int top, int bottom, int left, int right,
int borderType, const Scalar& value)
{
dst.create(src.rows + top + bottom, src.cols + left + right, src.type());
int offsets[] = {top, bottom, left, right};
copyMakeBorder(src, dst, offsets, borderType, value);
}
void copyMakeBorder(const InputArray _src, OutputArray _dst, int top, int bottom, int left,
int right, int borderType, const Scalar& value)
{
CV_Assert(borderType < 2);
Mat src = _src.getMat();
_dst.create(src.rows + top + bottom, src.cols + left + right, src.type());
Mat dst = _dst.getMat();
int offsets[] = {top, bottom, left, right};
copyMakeBorder(src, dst, offsets, borderType, value);
}
/************************** CropResizeMakeBorder **************************/
template <typename inMat, typename outMat>
void cropResizeMakeBorder(const inMat& src, outMat& dst, const Rect& rect, Size dsize,
int interpolation, int top, int left, const int borderType,
Scalar scalarV)
{
DvppOperatorDesc op;
op.addInput(src).addOutput(dst);
uint32_t taskID = 0;
int cnt = 1;
vpcCropResizeMakeBorderWarpper(op.chnId, op.inputDesc_, op.outputDesc_, cnt, &taskID, rect,
dsize, interpolation, borderType, scalarV, top, left);
uint32_t taskIDResult = taskID;
op.getResult(dst, taskIDResult);
}
void cropResizeMakeBorder(const AscendMat& src, AscendMat& dst, const Rect& rect, Size dsize,
double inv_scale_x, double inv_scale_y, int interpolation, int top,
int left, const int borderType, Scalar scalarV)
{
CV_Assert(borderType < 2);
Size ssize = src.size();
checkResize(ssize, dsize, inv_scale_x, inv_scale_y, interpolation);
dst.create(dsize.height + top, dsize.width + left, src.type());
cropResizeMakeBorder(src, dst, rect, dsize, interpolation, top, left, borderType, scalarV);
}
void cropResizeMakeBorder(const InputArray _src, OutputArray _dst, const Rect& rect, Size dsize,
double inv_scale_x, double inv_scale_y, int interpolation, int top,
int left, const int borderType, Scalar scalarV)
{
CV_Assert(borderType < 2);
Size ssize = _src.size();
checkResize(ssize, dsize, inv_scale_x, inv_scale_y, interpolation);
Mat src = _src.getMat();
_dst.create(dsize.height + top, dsize.width + left, src.type());
Mat dst = _dst.getMat();
cropResizeMakeBorder(src, dst, rect, dsize, interpolation, top, left, borderType, scalarV);
}
} // namespace cann
} // namespace cv
+310
View File
@@ -0,0 +1,310 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include <acl/acl.h>
#include <acl/dvpp/hi_dvpp.h>
#include "opencv2/dvpp_call.hpp"
#include <iostream>
#include <memory>
#include <cstdarg>
#include <string>
#define unlikely(expr) __builtin_expect(!!(expr), 0)
#define likely(expr) __builtin_expect(!!(expr), 1)
namespace cv
{
namespace cann
{
/******************************AscendPicDesc****************************/
AscendPicDesc& AscendPicDesc::setMemAlign()
{
if (Pic.picture_format == HI_PIXEL_FORMAT_BGR_888 ||
Pic.picture_format == HI_PIXEL_FORMAT_RGB_888 ||
Pic.picture_format == HI_PIXEL_FORMAT_YUV_PACKED_444)
{
widthAlignment = 16;
heightAlignment = 1;
sizeAlignment = 3;
sizeNum = 3;
}
else if (Pic.picture_format == HI_PIXEL_FORMAT_YUV_400)
{
widthAlignment = 16;
heightAlignment = 1;
sizeAlignment = 1;
sizeNum = 1;
}
else if (Pic.picture_format == HI_PIXEL_FORMAT_ARGB_8888 ||
Pic.picture_format == HI_PIXEL_FORMAT_ABGR_8888 ||
Pic.picture_format == HI_PIXEL_FORMAT_RGBA_8888 ||
Pic.picture_format == HI_PIXEL_FORMAT_BGRA_8888)
{
widthAlignment = 16;
heightAlignment = 1;
sizeAlignment = 4;
sizeNum = 4;
}
return *this;
}
AscendPicDesc& AscendPicDesc::setPic(hi_pixel_format _picture_format)
{
// set input
Pic.picture_format = _picture_format;
setMemAlign();
Pic.picture_width_stride = ALIGN_UP(Pic.picture_width, widthAlignment) * sizeAlignment;
Pic.picture_height_stride = ALIGN_UP(Pic.picture_height, heightAlignment);
Pic.picture_buffer_size =
Pic.picture_width_stride * Pic.picture_height_stride * sizeAlignment / sizeNum;
return *this;
}
std::shared_ptr<hi_void> AscendPicDesc::allocate()
{
Pic.picture_address = nullptr;
uint32_t ret = hi_mpi_dvpp_malloc(0, &Pic.picture_address, Pic.picture_buffer_size);
if (ret != HI_SUCCESS)
CV_Error(Error::StsBadFlag, "failed to malloc mem on dvpp");
return std::shared_ptr<hi_void>(Pic.picture_address, [](void* ptr) { hi_mpi_dvpp_free(ptr); });
}
AscendPicDesc::AscendPicDesc(const AscendMat& ascendMat, hi_pixel_format _picture_format)
{
Pic.picture_width = ascendMat.cols;
Pic.picture_height = ascendMat.rows;
setPic(_picture_format);
data = allocate();
}
AscendPicDesc::AscendPicDesc(const Mat& mat, hi_pixel_format _picture_format)
{
Pic.picture_width = mat.cols;
Pic.picture_height = mat.rows;
setPic(_picture_format);
data = allocate();
}
/******************************hi_mpi_vpc warppers****************************/
void vpcCropResizeWarpper(hi_vpc_chn chnId, hi_vpc_pic_info& inPic, hi_vpc_pic_info& outPic,
int cnt, uint32_t* taskID, const Rect& rect, Size dsize,
int interpolation)
{
hi_vpc_crop_region cropRegion = {.top_offset = static_cast<hi_u32>(rect.y),
.left_offset = static_cast<hi_u32>(rect.x),
.crop_width = static_cast<hi_u32>(rect.width),
.crop_height = static_cast<hi_u32>(rect.height)};
hi_vpc_resize_info resize_info = {.resize_width = static_cast<hi_u32>(dsize.width),
.resize_height = static_cast<hi_u32>(dsize.height),
.interpolation = static_cast<hi_u32>(interpolation)};
hi_vpc_crop_resize_region crop_resize_info[1];
crop_resize_info[0].dest_pic_info = outPic;
crop_resize_info[0].crop_region = cropRegion;
crop_resize_info[0].resize_info = resize_info;
uint32_t ret = hi_mpi_vpc_crop_resize(chnId, (const hi_vpc_pic_info*)&inPic, crop_resize_info,
cnt, taskID, -1);
if (ret != HI_SUCCESS)
CV_Error(Error::StsBadFlag, "failed to crop and resize image");
}
void vpcCopyMakeBorderWarpper(hi_vpc_chn chnId, hi_vpc_pic_info& inPic, hi_vpc_pic_info& outPic,
uint32_t* taskID, int* offsets, int bordertype, Scalar value)
{
hi_vpc_make_border_info make_border_info;
make_border_info = {.top = static_cast<hi_u32>(offsets[0]),
.bottom = static_cast<hi_u32>(offsets[1]),
.left = static_cast<hi_u32>(offsets[2]),
.right = static_cast<hi_u32>(offsets[3]),
.border_type = saturate_cast<hi_vpc_bord_type>(bordertype)};
if (outPic.picture_format == HI_PIXEL_FORMAT_BGR_888)
{
make_border_info.scalar_value.val[0] = value[2];
make_border_info.scalar_value.val[1] = value[1];
make_border_info.scalar_value.val[2] = value[0];
}
else if (outPic.picture_format == HI_PIXEL_FORMAT_YUV_400)
{
make_border_info.scalar_value.val[0] = value[0];
make_border_info.scalar_value.val[1] = value[1];
make_border_info.scalar_value.val[2] = value[2];
}
make_border_info.scalar_value.val[3] = value[3];
uint32_t ret = hi_mpi_vpc_copy_make_border(chnId, (const hi_vpc_pic_info*)&inPic, &outPic,
make_border_info, taskID, -1);
if (ret != HI_SUCCESS)
CV_Error(Error::StsBadFlag, "failed to crop and resize image");
}
void setBatchCropResizeMakeBorder(std::vector<AscendPicDesc>& outPicDesc,
hi_vpc_crop_resize_border_region crop_resize_make_border_info[],
const Rect& rect, Size dsize, int interpolation,
const int borderType, Scalar scalarV, int top, int left,
int batchSize)
{
hi_vpc_crop_region cropRegion = {.top_offset = static_cast<hi_u32>(rect.y),
.left_offset = static_cast<hi_u32>(rect.x),
.crop_width = static_cast<hi_u32>(rect.width),
.crop_height = static_cast<hi_u32>(rect.height)};
hi_vpc_resize_info resize_info = {.resize_width = static_cast<hi_u32>(dsize.width),
.resize_height = static_cast<hi_u32>(dsize.height),
.interpolation = static_cast<hi_u32>(interpolation)};
for (int i = 0; i < batchSize; i++)
{
crop_resize_make_border_info[i].dest_pic_info = outPicDesc[i].Pic;
crop_resize_make_border_info[i].crop_region = cropRegion;
crop_resize_make_border_info[i].resize_info = resize_info;
crop_resize_make_border_info[i].dest_top_offset = top;
crop_resize_make_border_info[i].dest_left_offset = left;
crop_resize_make_border_info[i].border_type = static_cast<hi_vpc_bord_type>(borderType);
if (crop_resize_make_border_info[i].dest_pic_info.picture_format == HI_PIXEL_FORMAT_BGR_888)
{
crop_resize_make_border_info[i].scalar_value.val[0] = scalarV[2];
crop_resize_make_border_info[i].scalar_value.val[1] = scalarV[1];
crop_resize_make_border_info[i].scalar_value.val[2] = scalarV[0];
}
else if (crop_resize_make_border_info[i].dest_pic_info.picture_format ==
HI_PIXEL_FORMAT_YUV_400)
{
crop_resize_make_border_info[i].scalar_value.val[0] = scalarV[0];
crop_resize_make_border_info[i].scalar_value.val[1] = scalarV[1];
crop_resize_make_border_info[i].scalar_value.val[2] = scalarV[2];
}
crop_resize_make_border_info[i].scalar_value.val[3] = scalarV[3];
}
}
void vpcCropResizeMakeBorderWarpper(hi_vpc_chn chnId, std::vector<AscendPicDesc>& inPicDesc,
std::vector<AscendPicDesc>& outPicDesc, int cnt,
uint32_t* taskID, const Rect& rect, Size dsize,
int interpolation, const int borderType, Scalar scalarV,
int top, int left)
{
hi_vpc_crop_resize_border_region crop_resize_make_border_info[1];
setBatchCropResizeMakeBorder(outPicDesc, crop_resize_make_border_info, rect, dsize,
interpolation, borderType, scalarV, top, left, 1);
uint32_t ret =
hi_mpi_vpc_crop_resize_make_border(chnId, (const hi_vpc_pic_info*)&inPicDesc[0].Pic,
crop_resize_make_border_info, cnt, taskID, -1);
if (ret != HI_SUCCESS)
CV_Error(Error::StsBadFlag, "failed to crop, resize and make border of image");
}
/******************************DvppOperatorDesc****************************/
DvppOperatorDesc& DvppOperatorDesc::reset()
{
uint32_t ret = hi_mpi_vpc_destroy_chn(chnId);
if (ret != HI_SUCCESS)
CV_Error(Error::StsBadFlag, "failed to destory DVPP vpc channel");
inputDesc_.clear();
outputDesc_.clear();
holder.clear();
return *this;
}
void initDvpp() { hi_mpi_sys_init(); }
void finalizeDvpp() { hi_mpi_sys_exit(); }
DvppOperatorDesc& DvppOperatorDesc::createChannel()
{
uint32_t ret = hi_mpi_vpc_sys_create_chn(&chnId, &stChnAttr);
if (ret != HI_SUCCESS)
CV_Error(Error::StsBadFlag, "failed to create DVPP vpc channel");
return *this;
}
// copy input array to dvpp memory
DvppOperatorDesc& DvppOperatorDesc::addInput(AscendPicDesc& picDesc)
{
inputDesc_.push_back(picDesc);
holder.insert(picDesc.data);
return *this;
}
template <typename inMat>
hi_pixel_format setPixelFormat(const inMat& mat)
{
CV_Assert(mat.channels() == 3 || mat.channels() == 1);
hi_pixel_format _picture_format;
if (mat.channels() == 3)
{
_picture_format = HI_PIXEL_FORMAT_BGR_888;
}
else if (mat.channels() == 1)
{
_picture_format = HI_PIXEL_FORMAT_YUV_400;
}
return _picture_format;
}
DvppOperatorDesc& DvppOperatorDesc::addInput(const AscendMat& mat)
{
Mat matHost;
mat.download(matHost);
return addInput(matHost);
}
DvppOperatorDesc& DvppOperatorDesc::addInput(const Mat& mat)
{
hi_pixel_format _picture_format = setPixelFormat(mat);
AscendPicDesc picDesc(mat, _picture_format);
aclrtMemcpy2d(picDesc.Pic.picture_address, picDesc.Pic.picture_width_stride, mat.data,
mat.step[0], mat.step[0], picDesc.Pic.picture_height, ACL_MEMCPY_HOST_TO_DEVICE);
return addInput(picDesc);
}
// malloc memory for output
DvppOperatorDesc& DvppOperatorDesc::addOutput(AscendPicDesc& picDesc)
{
outputDesc_.push_back(picDesc);
holder.insert(picDesc.data);
return *this;
}
DvppOperatorDesc& DvppOperatorDesc::addOutput(AscendMat& mat)
{
hi_pixel_format _picture_format = setPixelFormat(mat);
AscendPicDesc picDesc(mat, _picture_format);
return addOutput(picDesc);
}
DvppOperatorDesc& DvppOperatorDesc::addOutput(Mat& mat)
{
hi_pixel_format _picture_format = setPixelFormat(mat);
AscendPicDesc picDesc(mat, _picture_format);
return addOutput(picDesc);
}
// get process result and copy it to host/device
DvppOperatorDesc& DvppOperatorDesc::getResult(Mat& dst, uint32_t& taskIDResult)
{
uint32_t ret = hi_mpi_vpc_get_process_result(chnId, taskIDResult, -1);
if (ret != HI_SUCCESS)
CV_Error(Error::StsBadFlag, "failed to get process result.");
const uint32_t esz = CV_ELEM_SIZE(dst.type());
size_t step = esz * dst.cols;
aclrtMemcpy2d(dst.data, dst.step[0], outputDesc_[0].Pic.picture_address,
outputDesc_[0].Pic.picture_width_stride, dst.step[0],
outputDesc_[0].Pic.picture_height, ACL_MEMCPY_DEVICE_TO_HOST);
return *this;
}
DvppOperatorDesc& DvppOperatorDesc::getResult(AscendMat& dst, uint32_t& taskIDResult)
{
Mat matHost;
matHost.create(dst.rows, dst.cols, dst.type());
getResult(matHost, taskIDResult);
dst.upload(matHost);
return *this;
}
} // namespace cann
} // namespace cv
+471
View File
@@ -0,0 +1,471 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
namespace cv
{
namespace cann
{
static inline void applyMask(const AscendMat& src, AscendMat& dst, const AscendMat& mask,
AscendStream& stream)
{
int mtype = mask.type();
CV_Assert((mtype == CV_8UC1 || mtype == CV_8SC1) && mask.size() == src.size());
AscendMat onesMask, castedMask;
onesMask.create(mask.rows, mask.cols, mask.type());
OperatorRunner runner;
runner.setOp("Div")
.addInput(mask, "x1")
.addInput(mask, "x2")
.addOutput(onesMask, "y")
.run(stream);
onesMask.convertTo(castedMask, dst.depth(), stream);
arithm_op(src, castedMask, dst, "Mul", stream);
}
static inline void applyScale(const AscendMat& src, AscendMat& dst, float scale,
AscendStream& stream)
{
OperatorRunner runner;
arithm_op(src, scale, dst, "Muls", stream);
}
void arithm_op(const AscendMat& src1, const AscendMat& src2, AscendMat& dst, const char* op,
AscendStream& stream)
{
if (src2.empty())
arithm_op(src1, dst, op, stream);
else
{
OperatorRunner runner;
runner.setOp(op).addInput(src1, "x1").addInput(src2, "x2").addOutput(dst, "y").run(stream);
}
}
void arithm_op(const AscendMat& src, const Scalar& sc, AscendMat& dst, const char* op,
AscendStream& stream)
{
OperatorRunner runner;
runner.setOp(op)
.addInput(src, "x1")
.addInput(sc, src.type(), "x2")
.addOutput(dst, "y")
.run(stream);
}
void arithm_op(const Scalar& sc, const AscendMat& src, AscendMat& dst, const char* op,
AscendStream& stream)
{
OperatorRunner runner;
runner.setOp(op)
.addInput(sc, src.type(), "x1")
.addInput(src, "x2")
.addOutput(dst, "y")
.run(stream);
}
void arithm_op(const AscendMat& src, AscendMat& dst, const char* op, AscendStream& stream)
{
OperatorRunner runner;
runner.setOp(op).addInput(src, "x").addOutput(dst, "y").run(stream);
}
void arithm_op(const AscendMat& src, float scalar, AscendMat& dst, const char* op,
AscendStream& stream)
{
OperatorRunner runner;
runner.setOp(op).addInput(src, "x").addAttr(scalar, "value").addOutput(dst, "y").run(stream);
}
// Helper function for template arithm_op. all function called in template arithm_op should be
// done in both AscendMat and Scalar.
static void getInputInfo(const AscendMat& src, int& depth, int& cn, Size& size)
{
depth = src.depth();
cn = src.channels();
size = src.size();
}
static void getInputInfo(const Scalar& src, int& depth, int& cn, Size& size)
{
CV_UNUSED(src);
depth = -1;
cn = -1;
size = {-1, -1};
}
static void convert(const AscendMat& src, AscendMat& dst, AscendStream& stream)
{
src.convertTo(dst, CV_32F, stream);
}
static void convert(const Scalar& src, Scalar& dst, AscendStream& stream)
{
CV_UNUSED(stream);
dst = src;
}
template <typename T1, typename T2>
static void arithm_op(const T1& src1, const T2& src2, AscendMat& dst, const AscendMat& mask,
float scale, int dtype, const char* op, AscendStream& stream)
{
T1 castedSrc1;
T2 castedSrc2;
AscendMat castedRet;
int sdepth1, sdepth2, scn1, scn2;
Size ssize1, ssize2;
getInputInfo(src1, sdepth1, scn1, ssize1);
getInputInfo(src2, sdepth2, scn2, ssize2);
int sdepth = sdepth1 == -1 ? sdepth2 : sdepth1;
int cn = scn1 == -1 ? scn2 : scn1;
Size size = sdepth1 == -1 ? ssize2 : ssize1;
if (sdepth1 != -1 && sdepth2 != -1 && !ssize1.empty() && !ssize2.empty())
CV_Assert(sdepth1 == sdepth2 && scn1 == scn2 && ssize1 == ssize2);
if (dtype < 0)
dtype = sdepth;
const int ddepth = CV_MAT_DEPTH(dtype);
CV_Assert(sdepth <= CV_16F && ddepth <= CV_16F);
dst.create(size.height, size.width, CV_MAKE_TYPE(ddepth, cn));
// In order to achieve high accuracy, convert integers to float for calculation.
if (scale != 1 && dtype < CV_32F)
{
convert(src1, castedSrc1, stream);
convert(src2, castedSrc2, stream);
castedRet.create(size.height, size.width, CV_MAKE_TYPE(CV_32F, cn));
}
else
{
castedSrc1 = src1;
castedSrc2 = src2;
castedRet = dst;
}
// step1, calculate operator.
OperatorRunner runner;
arithm_op(castedSrc1, castedSrc2, castedRet, op, stream);
// step2, apply mask if need.
if (!mask.empty())
applyMask(castedRet, castedRet, mask, stream);
// step3, apply scale if need.
if (scale != 1)
applyScale(castedRet, castedRet, scale, stream);
// After rounding the result, convert the type to the original type.
if (castedRet.depth() != dst.depth())
{
runner.setOp("Round").addInput(castedRet, "x").addOutput(castedRet, "y").run(stream);
castedRet.convertTo(dst, stream);
}
}
static void arithm_op(const InputArray _src1, const InputArray _src2, OutputArray _dst,
const InputArray _mask, float scale, int dtype, const char* op,
AscendStream& stream)
{
const bool isScalar1 = (_src1.kind() == _InputArray::MATX);
const bool isScalar2 = (_src2.kind() == _InputArray::MATX);
if (isScalar1 && isScalar2)
CV_Error(Error::StsBadArg, "At list one matrix parameter shoule be passwd.");
AscendMat src1, src2, dst, mask;
Mat scalar;
if (!isScalar1 && !_src1.empty())
src1.upload(_src1, stream);
if (!isScalar2 && !_src2.empty())
src2.upload(_src2, stream);
if (!_mask.empty())
mask.upload(_mask, stream);
Scalar val;
if (isScalar1)
scalar = _src1.getMat();
else if (isScalar2)
scalar = _src2.getMat();
if (!scalar.empty())
{
CV_Assert(scalar.total() <= 4);
scalar.convertTo(Mat_<double>(scalar.rows, scalar.cols, &val[0]), CV_64F);
}
if (isScalar1)
arithm_op(val, src2, dst, mask, scale, dtype, op, stream);
else if (isScalar2)
arithm_op(src1, val, dst, mask, scale, dtype, op, stream);
else
arithm_op(src1, src2, dst, mask, scale, dtype, op, stream);
dst.download(_dst, stream);
}
// In order to supply more interfaces, differnet function declaration shoule be done.
void add(const InputArray src1, const InputArray src2, OutputArray dst, const InputArray mask,
int dtype, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, dtype, "Add", stream);
}
void add(const AscendMat& src1, const AscendMat& src2, AscendMat& dst, const AscendMat& mask,
int dtype, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, dtype, "Add", stream);
}
void add(const AscendMat& src1, const Scalar& src2, AscendMat& dst, const AscendMat& mask,
int dtype, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, dtype, "Add", stream);
}
void add(const Scalar& src1, const AscendMat& src2, AscendMat& dst, const AscendMat& mask,
int dtype, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, dtype, "Add", stream);
}
void subtract(const InputArray src1, const InputArray src2, OutputArray dst, const InputArray mask,
int dtype, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, dtype, "Sub", stream);
}
void subtract(const AscendMat& src1, const AscendMat& src2, AscendMat& dst, const AscendMat& mask,
int dtype, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, dtype, "Sub", stream);
}
void subtract(const AscendMat& src1, const Scalar& src2, AscendMat& dst, const AscendMat& mask,
int dtype, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, dtype, "Sub", stream);
}
void subtract(const Scalar& src1, const AscendMat& src2, AscendMat& dst, const AscendMat& mask,
int dtype, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, dtype, "Sub", stream);
}
void multiply(const InputArray src1, const InputArray src2, OutputArray dst, float scale, int dtype,
AscendStream& stream)
{
arithm_op(src1, src2, dst, noArray(), scale, dtype, "Mul", stream);
}
void multiply(const AscendMat& src1, const AscendMat& src2, AscendMat& dst, float scale, int dtype,
AscendStream& stream)
{
arithm_op(src1, src2, dst, AscendMat(), scale, dtype, "Mul", stream);
}
void multiply(const AscendMat& src1, const Scalar& src2, AscendMat& dst, float scale, int dtype,
AscendStream& stream)
{
arithm_op(src1, src2, dst, AscendMat(), scale, dtype, "Mul", stream);
}
void multiply(const Scalar& src1, const AscendMat& src2, AscendMat& dst, float scale, int dtype,
AscendStream& stream)
{
arithm_op(src1, src2, dst, AscendMat(), scale, dtype, "Mul", stream);
}
void divide(const InputArray src1, const InputArray src2, OutputArray dst, float scale, int dtype,
AscendStream& stream)
{
arithm_op(src1, src2, dst, noArray(), scale, dtype, "RealDiv", stream);
}
void divide(const AscendMat& src1, const AscendMat& src2, AscendMat& dst, float scale, int dtype,
AscendStream& stream)
{
arithm_op(src1, src2, dst, AscendMat(), scale, dtype, "RealDiv", stream);
}
void divide(const AscendMat& src1, const Scalar& src2, AscendMat& dst, float scale, int dtype,
AscendStream& stream)
{
arithm_op(src1, src2, dst, AscendMat(), scale, dtype, "RealDiv", stream);
}
void divide(const Scalar& src1, const AscendMat& src2, AscendMat& dst, float scale, int dtype,
AscendStream& stream)
{
arithm_op(src1, src2, dst, AscendMat(), scale, dtype, "RealDiv", stream);
}
void bitwise_and(const InputArray src1, const InputArray src2, OutputArray dst,
const InputArray mask, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseAnd", stream);
}
void bitwise_and(const AscendMat& src1, const AscendMat& src2, AscendMat& dst,
const AscendMat& mask, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseAnd", stream);
}
void bitwise_and(const AscendMat& src1, const Scalar& src2, AscendMat& dst, const AscendMat& mask,
AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseAnd", stream);
}
void bitwise_and(const Scalar& src1, const AscendMat& src2, AscendMat& dst, const AscendMat& mask,
AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseAnd", stream);
}
void bitwise_or(const InputArray src1, const InputArray src2, OutputArray dst,
const InputArray mask, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseOr", stream);
}
void bitwise_or(const AscendMat& src1, const AscendMat& src2, AscendMat& dst, const AscendMat& mask,
AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseOr", stream);
}
void bitwise_or(const AscendMat& src1, const Scalar& src2, AscendMat& dst, const AscendMat& mask,
AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseOr", stream);
}
void bitwise_or(const Scalar& src1, const AscendMat& src2, AscendMat& dst, const AscendMat& mask,
AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseOr", stream);
}
void bitwise_xor(const InputArray src1, const InputArray src2, OutputArray dst,
const InputArray mask, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseXor", stream);
}
void bitwise_xor(const AscendMat& src1, const AscendMat& src2, AscendMat& dst,
const AscendMat& mask, AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseXor", stream);
}
void bitwise_xor(const AscendMat& src1, const Scalar& src2, AscendMat& dst, const AscendMat& mask,
AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseXor", stream);
}
void bitwise_xor(const Scalar& src1, const AscendMat& src2, AscendMat& dst, const AscendMat& mask,
AscendStream& stream)
{
arithm_op(src1, src2, dst, mask, 1, -1, "BitwiseXor", stream);
}
void bitwise_not(const InputArray src, OutputArray dst, const InputArray mask, AscendStream& stream)
{
arithm_op(src, noArray(), dst, mask, 1, -1, "Invert", stream);
}
void bitwise_not(const AscendMat& src, AscendMat& dst, const AscendMat& mask, AscendStream& stream)
{
arithm_op(src, AscendMat(), dst, mask, 1, -1, "Invert", stream);
}
void addWeighted(const AscendMat& src1, double alpha, const AscendMat& src2, double beta,
double gamma, AscendMat& dst, int dtype, AscendStream& stream)
{
if (dtype < 0)
dtype = src1.depth();
CV_Assert(src2.depth() == src1.depth() && src2.size() == src1.size() &&
src1.channels() == src2.channels());
int type = CV_MAKE_TYPE(dtype, src1.channels());
dst.create(src1.rows, src1.cols, type);
// TODO: Consider overflow, should extend type or not?
AscendMat src1Weighted(src1.size(), type), src2Weighted(src1.size(), type),
srcWeightedSumRet(src1.size(), type);
arithm_op(src1, (float)alpha, src1Weighted, "Muls", stream);
arithm_op(src2, (float)beta, src2Weighted, "Muls", stream);
arithm_op(src1Weighted, src2Weighted, srcWeightedSumRet, "Add", stream);
arithm_op(srcWeightedSumRet, (float)gamma, dst, "Adds", stream);
}
void addWeighted(const InputArray _src1, double alpha, const InputArray _src2, double beta,
double gamma, OutputArray _dst, int dtype, AscendStream& stream)
{
AscendMat src1, src2, dst;
src1.upload(_src1, stream);
src2.upload(_src2, stream);
addWeighted(src1, alpha, src2, beta, gamma, dst, dtype, stream);
dst.download(_dst, stream);
}
double threshold(const AscendMat& src, AscendMat& dst, double thresh, double maxval, int type,
AscendStream& stream)
{
// ThresholdTypes is defined in opencv2/imgproc, This type is the only Symbol we need.
// Add imgproc to dependence is too heavy, use magic number instead.
CV_Assert(type <= 4 /*THRESH_TOZERO_INV*/);
AscendMat threshMat(src.size(), src.type());
dst.create(src.rows, src.cols, src.type());
if (src.depth() == CV_8U || src.depth() == CV_8S || src.depth() == CV_16S ||
src.depth() == CV_32S || src.depth() == CV_32F || src.depth() == CV_16F)
{
ThresholdOpencvTilingData tiling;
tiling.maxVal = maxval;
tiling.thresh = thresh;
// AscendMat memory will be align to 32B, it's safe to set totalLengh a little bigger.
size_t totalBytes = src.rows * src.cols * src.channels();
tiling.totalLength = ALIGN_UP(totalBytes, 32);
tiling.threshType = type;
tiling.dtype = src.depth();
kernel_launch(aclrtlaunch_threshold_opencv, stream, tiling, src.data.get(), dst.data.get());
}
else
CV_Error(Error::StsUnsupportedFormat, "");
return thresh;
}
double threshold(const InputArray _src, OutputArray _dst, double thresh, double maxval, int type,
AscendStream& stream)
{
AscendMat src, dst;
src.upload(_src, stream);
dst.create(src.rows, src.cols, src.type());
double ret = threshold(src, dst, thresh, maxval, type, stream);
dst.download(_dst, stream);
return ret;
}
} // namespace cann
} // namespace cv
+17
View File
@@ -0,0 +1,17 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef __OPENCV_PRECOMP_H__
#define __OPENCV_PRECOMP_H__
#include "opencv2/cann.hpp"
#include "opencv2/stream_accessor.hpp"
#include "opencv2/cann_call.hpp"
#include "opencv2/cann_interface.hpp"
#include "opencv2/cann_private.hpp"
#include "opencv2/dvpp_call.hpp"
#include "opencv2/ascendc_kernels.hpp"
#define ALIGN_UP(num, align) (((num) + (align) - 1) & ~((align) - 1))
#endif /* __OPENCV_PRECOMP_H__ */