C++ 中类似 Python 的切片操作
Posted
技术标签:
【中文标题】C++ 中类似 Python 的切片操作【英文标题】:Python like Slicing operation in c++ 【发布时间】:2020-07-27 19:53:43 【问题描述】:我有以下代码,其中 'Snap.JPG' 是 RGB 格式类型。
import cv2
img = cv2.imread("./Snap.JPG")
img[:,:,:2] = 255
cv2.imshow("Img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
我想将此代码转换为 c++。实现img[:,:,:2] = 255
部分代码的最快方法是什么?通道拆分和合并是我知道的选项之一,但是有没有更聪明的方法可以在 c++ 中进行切片?
编辑: 抱歉,我应该在输出中提到我想要的。我需要一个淡入淡出的效果,因为我想在它上面叠加一张图。
【问题讨论】:
您能举例说明img[:,:,:2]
的作用吗?
我认为它的计算结果是一个左值表达式。
由于涉及副本,拆分和合并肯定不是最佳的。编译器应该能够优化所有元素的简单循环,您只覆盖Vec3b
的前两个部分。然后可能将其转换为 cv::ParallelLoopBody
的派生类,以便您可以使用 cv::parallel_for_
... 运行它...或者这些天 lambda 也可以。
@cigien,我猜它会将所有i
和j
和k = 0, 1
设置为img[i, j, k]
。
@cigien 它为仅包含前两个通道的原始数组创建了一个视图。然后将 255 分配给第一个和第二个通道中的所有值。鉴于图像是 BGR(它是 OpenCV),这意味着图像中所有像素的所有蓝色和绿色强度都设置为 255。
【参考方案1】:
这是一个如何改变像素的例子:
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
int main(int argc, char** argv)
cv::Mat src_image = cv::imread("image.jpg", CV_LOAD_IMAGE_COLOR);
if(!src_image.data)
std::cout << "Error: the image wasn't correctly loaded." << std::endl;
return -1;
cv::Mat image = src_image.clone();
// We iterate over all pixels of the image
for(int r = 0; r < image.rows; r++)
// We obtain a pointer to the beginning of row r
cv::Vec3b* ptr = image.ptr<cv::Vec3b>(r);
for(int c = 0; c < image.cols; c++)
ptr[c] = cv::Vec3b(255, 255, ptr[c][2]);
cv::imshow("Inverted Image", image);
cv::waitKey();
return 0;
【讨论】:
【参考方案2】:感谢@Manuel 的回复,效果很好。但我可以用更快的速度达到同样的效果。我已经添加了我的代码 sn-ps inline 你的代码。
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <iomanip>
int main(int argc, char** argv)
clock_t start, end;
cv::Mat src_image = cv::imread("Snap.JPG", CV_LOAD_IMAGE_COLOR);
if(!src_image.data)
std::cout << "Error: the image wasn't correctly loaded." << std::endl;
return -1;
/* 1st method */
cv::Mat image = src_image.clone();
start = clock();
// We iterate over all pixels of the image
for(int r = 0; r < image.rows; r++)
// We obtain a pointer to the beginning of row r
cv::Vec3b* ptr = image.ptr<cv::Vec3b>(r);
for(int c = 0; c < image.cols; c++)
ptr[c] = cv::Vec3b(255, 255, ptr[c][2]);
end = clock();
double time_taken = double(end - start) / double(CLOCKS_PER_SEC);
std::cout << "Time taken by 1st method : " << std::fixed << time_taken << std::setprecision(5);
std::cout << " sec " << std::endl;
/* 2nd Method */
start = clock();
src_image = src_image | cv::Scalar(255, 255, 0);
end = clock();
time_taken = double(end - start) / double(CLOCKS_PER_SEC);
std::cout << "Time taken by 2nd method : " << std::fixed << time_taken << std::setprecision(5);
std::cout << " sec " << std::endl;
bool isEqual = (sum(src_image != image) == cv::Scalar(0,0,0,0));
if (isEqual)
std::cout << "\nIdentical Mats !" << std::endl;
cv::imshow("Inverted Image", image);
cv::waitKey();
return 0;
输出如下:
Time taken by 1st method : 0.001765 sec
Time taken by 2nd method : 0.00011 sec
Identical Mats !
【讨论】:
以上是关于C++ 中类似 Python 的切片操作的主要内容,如果未能解决你的问题,请参考以下文章