【问题标题】:remove all black pixels and get only required image using C++ (OpenCV)使用 C++ (OpenCV) 删除所有黑色像素并仅获取所需的图像
【发布时间】:2020-03-08 05:52:35
【问题描述】:

我已经尝试使用 findNonZero 和 boundingRect。但没有什么能帮助我。 我是 C++ OpenCV 的新手。我使用涉及 NumPy 的 Python OpenCV 做到了这一点,但不幸的是我无法在 C++ 中做同样的事情。

输入图像

Python:

def crop_with_arg(refactor_image):
  mask = refactor_image > 0
  coord = np.argwhere(mask)
  x0, y0 = coord.min(axis=0)
  x1, y1 = coord.max(axis=0) + 1
  cropped = refactor_image[x0:x1, y0:y1]
  return cropped

 def crop_image(image_crop, tol=50):
    mask = image_crop > tol
    return image_crop[np.ix_(mask.any(1), mask.any(0))]

 compressed_img = crop_with_arg(gray) 
 croppped_image = crop_image(compressed_img, tol=50)

我正在用 Objective C++ 编写代码来为 iOS 提供包装器。

【问题讨论】:

  • 您应该发布一些代码,例如可以运行的 Python 代码和无法运行的 C++ 代码。
  • 什么不起作用?输出不正确的方式是什么?到目前为止你做了什么调试?你有没有看到if实际上是在你的调试器或你的调试打印中输入的? nonBlackList 在循环之后是否正确填充? bb 的边界是否正确?如果不是,它们是什么,它们应该是什么?
  • >什么不起作用?种植不起作用。 > 输出不正确的方式是什么?我得到了相同的图像,没有进行裁剪>到目前为止你做了什么调试?我试图理解数据并查看循环是否正常工作。 x 和 y 已填充。 > bb 的边界没有 x 和 y 值。因此种植不起作用。此 C++ 代码在我的场景中不起作用。因此问我是否走在正确的道路上
  • “y 值未填充”是什么意思?创建的点没有 y 值?我认为可能是问题的一件事是您在graycloned.at<cv::Vec2b>(j,i) 中的x-y 顺序与cv::Point(i,j) 中的不同( (j,i) 与 (i,j) )。如果 i 是列,是否应该改为 graycloned.at<cv::Vec2b>(i,j)
  • 那是菜鸟的错误!我确实纠正了它。现在我得到了这些值。 bb的打印说明:(cv::Rect) bb = (x = -390252292, y = 1, width = 72760040, height = 1)

标签: c++ algorithm opencv image-preprocessing


【解决方案1】:

我认为这样的事情,使用cv::boundingRect(),会非常有效:

#include <iostream>
#include <opencv2/opencv.hpp>

int
main(int argc,char*argv[])
{
    // Load image as greyscale
    cv::Mat im = cv::imread("thing.jpg", cv::IMREAD_GRAYSCALE);

    // Threshold image at 128
    cv::Mat thresh;
    cv::threshold(im, thresh, 128, 255, cv::THRESH_BINARY);

    // Do the actual work
    double t = (double)cv::getTickCount();
    cv::Rect ROI = cv::boundingRect(thresh);
    t = ((double)cv::getTickCount() - t)/cv::getTickFrequency(); 

    // Print timing and results
    std::cout << "Time: " << t*1000.0 << "ms" << std::endl;
    std::cout << ROI << std::endl;
}

样本输出

Time: 0.317279ms
[253 x 48 from (113, 503)]

顺便说一句,您可以使用 ImageMagick 从命令行更简单地执行此操作,大多数 Linux 发行版中都包含该工具,并且可用于 macOS 和 Linux:

# Print coordinates of trim-box
convert thing.jpg -threshold 50% -format %@ info:
253x48+113+503

或者,实际进行修剪:

convert thing.jpg -threshold 50% -trim result.jpg

关键字:图像处理、OpenCV、C++、trim、trim box、trim-box、crop、crop-box、border、bordering、remove border、trim border、ROI、boundingRect()、 cv::boundingRect()

【讨论】:

  • 这是 ios 的。不过我会检查一下。谢谢
【解决方案2】:

对于灰度图像,以下代码完美运行。

值 50 是可以根据已完成的预处理设置的阈值限制。

grayThres = gray > 50;
graycloned = grayThres.clone();
std::vector<cv::Point> nonBlackList;
nonBlackList.reserve(graycloned.rows*graycloned.cols);

for(int j=0; j<graycloned.rows; ++j)
    for(int i=0; i<graycloned.cols; ++i)
    {
        // if not black: add to the list
        if(graycloned.at<cv::Vec2b>(j,i) != cv::Vec2b(0,0))
        {
            nonBlackList.push_back(cv::Point(j,i));
        }
    }
// create bounding rect around those points
cv::Rect bb = cv::boundingRect(nonBlackList);
cv:: Mat returnImage = gray(bb);

【讨论】:

  • 同样可以通过调用2个OCV函数cv::thresholdcv::findNonZero实现
猜你喜欢
  • 2017-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-18
  • 2020-03-27
  • 2018-09-28
  • 1970-01-01
  • 2021-06-27
相关资源
最近更新 更多